当前位置: 首页 > news >正文

C++测开,自动化测试,业务(第一段实习)

目录

🌼前言

一,实习经历怎么写简历

🌹业务理解

🎂结构化表达

二,实习

🦂技术和流程卡点

🔑实习收获 / 代码风格

三,测试理论,用例设计,工具链

🌳测试理论 / 用例设计

🍌工作内容

四,交互式 / 非交互式自动化测试实践

📱交互式自动化测试

👖非交互式自动化测试

📕手动确定覆盖率

五,测试工程构建 / 主要业务

🐎测试工程构建

🐘主要业务(API 的二次开发)

概念

客户如何工作

API 和 平台的关系

六,测试分级 / bug 排查 / 单元测试规范

🐱测试用例分级

🐉BUG排查 / 定位

🐒测试模式

🏢单元测试规范

🍑优秀的单元测试

🌼单元测试细节 / 项目单测流程

七,代码质量问题案例

🌊案例

🌼POD 对象


🌼前言

3个月的实习,之前就面了 15 分钟,闲聊 5 分钟,隔天发的 offer

毕竟只是任务重,招点实习生来打杂,以下总结下实习经验

一,实习经历怎么写简历

🌹业务理解

业务全套首先要弄清楚,因为面试官不了解这个行业,你能把前前后后的产品逻辑讲清楚,他就觉得你学习能力还不错

结合公司文档,将公司文档中,一些和自己平时工作有关联的东西,加以记录和理解

(不是在内网拷贝,而且用自己话,记录下来)

后面面试时,能讲清楚逻辑和细节,就行

比如 RAII 机制的一些宏,具体怎么实现的,涉及 C++11 的哪些特性,解决了什么问题等等

实习中,一整套的工作流程是怎样的,有什么比较热门的技术,在日常的功能测试,交互式,非交互式测试中使用了

或者,你平时测试的那些 API 接口,在整个业务的上下游,整天的链路逻辑,你处于哪个位置等

⑤ 

实习的一些收获,比如干活前,需要明确需求和 ddl,防止返工,大胆问

或者怎么处理分支冲突,以及 Git Extension, GitLab 的使用,还有宏失败了怎么处理

🎂结构化表达

 ① 

实习经历分:工作职责 / 技术和框架 / 实习收获,三个方面去写

比如使用 C++ Catch2 测试框架,GenCMake 自动添加 CMake,.mac 宏录制和自动化测试跑宏,遇到一个新的接口怎么区测试的完整流程

③ 

实习做的东西,比如写了 100+ 不同类型接口的测试用例,完成 30 个接口覆盖率的提升,发现 9 个接口 BUG,3 天时间熟悉产品的基本操作

二,实习

🦂技术和流程卡点

① 

技术上,最开始的宏录制,容易失败,因为存在无关操作,比如点击了无关的点,缩放了屏幕大小,覆盖已保存的文件;

或者,没有区分不同类型的变量,误判了父类型和子类型等等

② 

测试流程上,不熟悉整个从 VS 检索接口注释,到平台尝试复现 API 功能,再到 VScode 搜索历史代码的整个流程

③ 

出现分支冲突,不知道如何处理,比如常见的 commit, pull merge, fetch all,以及 stash, stash pop 等;

分支冲突时可以注释他人的代码;或者询问 mentor 谁修改了这个文件

部门沟通上,你要和产品,测试,开发进行对接,需要频繁的沟通,以保证自己的工作效率(比如人均 3 次 / 天)

某个功能点,产品比你了解的更清楚;某个接口的具体实现,问开发也是最好的选择

比如接口返回值,位于平台哪里,函数调用需要注意的点,某些没跑进覆盖率的代码实现

⑤ 遇到困惑的点,积极跟 mentor 沟通,不要闭门造车

🔑实习收获 / 代码风格

① 

技术上,熟悉了 Catch2 的部分操作,学会处理分支冲突,宏失败怎么排查,以及记录遇到的问题避免重复提问,还有 P1,P2 功能性+无效等价类+边界+异常场景的测试用例怎么写

② 

代码风格上,首先,避免使用 new / delete, malloc / free 这一套,容易忘记释放导致内存泄露,而应该使用 C_AUTO 类宏,来声明指针,数组,句柄,锁等;

但是部分接口,需要接收已有的地址,就不能用 C_AUTO 宏来初始化,而应该使用 C++ 自带的初始化,比如 svxDeskFace deskFace{};

频繁被调用的代码,可以封装为函数,放到公用的头文件里

④ 

代码中,注释不要太多,但是基本的接下来上百行代码,别人知道你在干什么就行,比如 Catch2 的 WHEN("niu bi plus")

三,测试理论,用例设计,工具链

🌳测试理论 / 用例设计

从公司文档学习:白盒测试,黑盒测试,测试流程,测试用例的设计过程

② 

讲讲你们自动化测试这一块的内容

实习时,git 如何协作

④ 

公司的工具链是怎样的

🍌工作内容

① 

主要工作:API 二次开发自动化测试

② 

负责公司 API 的自动化测试,优化覆盖率,确保 API 功能与平台一致

③ 

使用 C++ 和 Catch2 框架,进行单元测试和集成测试

④ 

使用 Git 进行版本控制,参与 GitLab 分支管理,合并分支冲突

通过录宏 / 跑宏,交互式 / 非交互式相结合的方式测试

在 GitLab 登记问题,提供详细复现步骤和日志文件,便于开发快速定位问题

四,交互式 / 非交互式自动化测试实践

📱交互式自动化测试

利用公司平台已有的宏测试系统实现自动化测试

优点:测试上下文易构建,通过平台操作,测试场景容易扩展,直接在平台添加测试宏

缺点:交互式只能构建正常场景;测试接口容易受其他模块干扰;不贴合客户真实使用场景

适用场景:平台命令封装类接口;UI 界面相关的显示接口

👖非交互式自动化测试

使用 Catch2 单元测试框架实现

② 

优点:贴合客户使用场景;更容易实现参数层面的枚举

缺点

测试上下文难构建,只能调用其他 API 进行

部分入参难以确定

部分命令场景,对入参有要求时,难以使用现有 API 指定

适用场景:数据查询类接口,数学计算类接口

📕手动确定覆盖率

当 OpenCppCoverage 的覆盖率还未更新,需要手动获取覆盖率时

② 

可以在测试用例中,每个调用 API 的位置,打断点,f11,step into 源码

找到 API 的实现后,在每个小分支的入口处,都打上断点,然后针对测试用例中调用的 API,不断 step into,在源码中 continue

每跑进源码的一个小分支,就取消分支入口处断点

最后源码中尚未取消的断点,就是源码未覆盖的分支,然后针对未覆盖分支处调用的其他 API 和 参数,找开发问一下

五,测试工程构建 / 主要业务

🐎测试工程构建

类似启动 vs 工程时,双击 .sln 的操作:双击 generate.bat 构建出对应的 msbuild 工程并启动 VS2019

一个测试用例的构建包括:

a. 测试场景的初始化(测试上下文的构建
b. 执行被测试的 API 接口

c. 对测试结果断言检查

对于 Catch2 测试框架,平台的运行环境属于全局变量,声明周期存在于整个测试流程中,所以每个测试场景运行结束时,无法自动还原环境,需要手动还原

🐘主要业务(API 的二次开发)

概念

二次开发,就是在现有软件的基础上,进行定制修改和功能扩展,实现自己想要的功能

客户需要借助二次开发的 API 进行开发

这个 API 接口可以理解为,根据客户的要求,将平台内部的某个函数,再做一层封装和处理后,再给用户使用

二次开发的 API 接口,一般对应平台的一个功能或子功能,而对于客户来说,他只需要知道 API 的函数名,功能,以及输入输出

客户如何工作

客户在开发环境中,引用二次开发 API 的头文件(声明),链接静态库 .lib(实现),就可以直接使用这批接口

客户通过这批 API,实现自己的功能,并且把代码封装成一个函数,将函数注册成自定义命令,然后编译生成动态库(.dll),也就是二次开发插件

接着运行我们的平台,加载 .dll 插件,就能使用用户自定义的功能了

API 和 平台的关系

API 测试一般对应界面上某个功能,与平台交互就能测试;

或者通过调用平台内部的功能函数进行测试

所以对 API 进行测试,也能测到平台的功能

API 测试用例失败,可能是二次开发 API 的问题,也可能是对应功能的内部函数出了问题

平台命令 / 底层函数的变更,也会对 API 产生影响

a. 显示影响:api 对应某个命令,命令发生了变化,比如增加了入参选项,对应的 api 也要同步更新

b. 隐式影响: api 使用了某个内部函数 或 底层机制,额你不函数逻辑变更,或机制变更

在不确定项目对 api 是否有影响时

a. 开发要主动向 api 开发进行确认

b. 测试也要提升 api 的覆盖率,并且及时全量地运行 api 自动化测试,检测项目是否引入 api 问题(master 主干分支,每周进行集成测试)

六,测试分级 / bug 排查 / 单元测试规范

🐱测试用例分级

① 功能性:有效等价类(输入性 + 功能性),边界,对平台运行环境的影响

  a. 有些接口会影响全局变量,导致当前接口运行正常,但是其他测试用例因此失败

② 健壮性:无效等价类 + 其他常见错误异常场景

  a.

接口会针对不同的错误场景,返回不同的错误码

一类错误码:客户经常犯的(非法输入),便于客户调试问题

另一类错误码:针对接口内部或平台底层代码的处理,出现异常(内存错误,读取对象数据失败),便于开发排查问题

  b. 还要根据接口本身的功能,测试的经验,反推可能存在的错误场景

③ 易用性:命令规范,接口易用,注释正确

④ 兼容性

⑤ 效率测试

⑥ 回归测试

🐉BUG排查 / 定位

逐步排查接口 bug 时,不要用 for,会增大排查难度

复现问题,定位问题(用例 / 环境 / 接口实现 / 平台功能),查阅文档和源码,覆盖率分析和断点测试,和开发产品测试沟通,猜想与验证,查看日志,内存检测

特别注意:接口的依赖关系 + 前置条件 + 易混淆类型

🐒测试模式

① 传统测试模式

使用 TEST_CASE 定义单元测试

(test_name [,tags]) {}

test_name:测试用例名称,任意的,需要全局唯一

tags:标签名,用 [] 将每个标签抱起来,逗号分隔,不用全局唯一

② BDD模式

行为驱动开发(behaviour driven development),通过在 GIVEN,WHEN,THEN 中,自然语言书写测试用例的信息,扩展了测试驱动开发的方法

Ⅰ 其中,GIVEN 前提条件 = 测试场景初始化 + 构建入参

Ⅱ 然后,WHEN 做的事情 = 执行被测试 api

Ⅲ 最后,THEN 结果 = 对 api 调用后的返回值,入参,出餐进行检测

🏢单元测试规范

① 

平台的测试案例使用 BDD-style,一个完整的单元测试案例包括

Arrange(初始化),Action(执行),Assert(断言)

编码原则:边界,正确输入,设计与需求相结合,错误输入,预期结果

编码规范:每个文件只对应一个接口  +  所有单元测试案例必须有描述

④ 测试维度

接口功能性(接口的正确性 + 一定条件下正常被调用 + 返回预期结果)

局部数据结构(变量是否有初始值 + 变量是否溢出)、

边界(指针 + 数值 + 字符串 + 集合)

异常处理(异常可否被识别 + 识别后是否有处理)

使用 OpenCppCoverage 工具,分析测试用例对代码的覆盖率

🍑优秀的单元测试

a. 自动化的

b. 很容易实现

c. 第二天还有意义

d. 任何人都可以一键运行

e. 运行速度很快

f. 结果稳定,多次运行同一个测试用例,总是返回相同的结果

g. 能够完全控制被测试的单元

h. 完全隔离的(不依赖其他所有测试用例)

i. 如果它失败了,可以很容易发现什么是预期的结果,可以很快定位问题所在

🌼单元测试细节 / 项目单测流程

单元测试细节

a. 底层遗留代码的测试:静态测试(开发自己代码走查)+  动态测试(编写测试用例)

b. 是否为所有共有接口编写用例:资源有限时,有限覆盖高频,关键,危险接口

c. 推动开发改造接口:剔除非必要接口,提高接口容错能力,重构复杂接口,配套demo测试

d. 测试方案:确定子模块测试顺序,获取接口清单 和 调用频次,重点关注危险行为

e. 测试过程:对照接口标注和注释,检查逻辑完整性,异常处理,全局变量使用,边界等

f. 测试用例编写:结合黑盒 / 白盒,逻辑覆盖,边界,错误场景补充;模拟平台实际调用,发挥想象力设计异常输入

项目单测流程

Ⅰ 输入:项目核心文档 + 设计方案

Ⅱ 输出:测试方案 + 测试报告 + 用例代码

Ⅲ 执行流程

a. 初步拟定测试方案,用例清单

b. 用例评审(上级,项目经理,项目开发)

c. 搭建测试环境,测试场景构建

d. 引入开发代码,运行测试用例

e. 反馈测试结果,bug 跟踪,生成测试报告

f. 开发人员处理 bug 后,进行回归测试

g. 测试代码集成(开发源码集成后) -- 集成:多个组件模块合并到同一个系统

h. 测试用例加入主干定期测试

七,代码质量问题案例

🌊案例

① 超大文件

单个源文件几千行,很难维护和理解,如果某个超大的 .cpp,被多个人同时修改,合并冲突的概率就会大大增加,影响开发效率

② 超长函数

函数超过 200 行,逻辑复杂,难以测试和复用,如果某个超长函数被修改,容易引发连锁 bug,导致回滚上线

  void processOrder() {// ... 500行代码 ...}

③ 超长的类

类中成员变量和方法过多,违反单一职责原则,最好拆分为多个小的类,按功能聚合

④ 单个函数多个职责

一个函数既做数据校验,又做业务处理,还做日志记录

void handleUserRequest() {validateInput();processBusiness();logOperation();
}
// 建议拆分为 validate(), process(), log() 三个函数

⑤ 需要频繁更新的函数

频繁变动的函数,容易引入回归 bug,如果某个函数的逻辑频繁变动,未做好单元测试,容易导致线上事故

⑥ 不必要的接口依赖

如果模块 A 依赖模块 B 内部的实现,导致 A 的变更影响 B,最好进行接口隔离,减少耦合

⑦ 不必要的实现依赖

如果项目直接依赖第三方库的实现细节,升级时风险很大,容易产生大量编译错误

⑧ 逆模块依赖的接口调用

如果低层模块反向依赖高层模块,会破坏分层结构

⑨ 模块私有接口被外部调用

本应只在模块内部使用的函数,被外部调用,导致维护困难

⑩ 滥用全局变量

全局变量被多处修改,难以追踪和调试,比如被多线程同时修改,导致数据错乱

① 不必要的局部静态变量

静态变量声明周期长,容易引发资源泄露或线程安全问题

② 难理解的名称缩写

比如 tmp, foo, bar

③ 抽象的函数命名

比如 doTask(), handle(),无法体现具体功能

④ 不必要的模板编程

追求泛型而滥用模板编程,导致代码复杂难懂,新人难以上手维护

⑤ 无意义的函数注释

注释应说明返回值,入参,出参,边界,注意事项等

// this is a function

⑥ 过长的参数列表

函数参数不要超过 5 个,否则易出错,考虑封装为结构体或对象传参

⑦ 缺乏单元测试

无单元测试,线上热修复容易引发故障

⑧ 重复代码

同样的逻辑在多个地方实现,维护成本高,最好提取为公共函数或工具类

⑨ 通用处理方法--插入大量针对个别对象的特殊处理逻辑

如,主流程代码被特殊 case 污染,导致难以阅读和修改

⑩ 对非 pod 对象进行裸内存操作

如,直接 memcpy, memset 非 POD 类型对象,容易产生 undefined 行为

⑩① 混合编码风格

C/C++ 混用,代码风格不统一,容易内存泄露

🌼POD 对象

什么是 POD 

Plain Old Data,普通的旧的数据 

POD 类型:像 C 语言结构体那样,没有复杂构造 / 析构函数,没有虚函数,没有继承,没有非静态 C++类 或 结构体

本质:内存布局简单,和 C 语言的 struct 一样,可以安全使用 memcpy, memset 等 C 函数直接操作内存的对象

裸内存操作

直接对内存进行原始的字节级别的操作,而不是经过对象的构造,析构,拷贝等 C++ 语义

比如 memcpy(拷贝一段内存),memset(填充一段内存)

malloc / free(直接分配 / 释放原始内存块,不调用构造 / 析构函数)

realloc(直接调整内存块大小)

本质

① 只关心内存的字节内容,不关心对象的声明周期,构造,析构,拷贝等 C++ 语义

② 适用于 C 语言风格的 POD (老古董类型)对象

③ 对于有复杂成员(std::string, vector, 虚函数, 继承等)的 C++ 对象,裸内存操作,会破坏对象内部的状态,导致 Undefined 行为

建议

 ① 判断 POD 场景

a. 只有简单结构体(全是 int, float, char 等基础类型的 struct)

b. 只要有 C++ 特性(string, vector, 虚函数, 继承, 构造, 析构等)就不是 POD

② 不要对非 POD 对象用 memcpy / memset

比如

struct User {std::string name;int age;
};User u1, u2;memcpy(&u2, &u1, sizeof(User)); // wrong! User not POD!

③ 安全做法

a. 对于非 POD 对象,通过拷贝构造,赋值运算符,swap 等 C++ 标准方法,不用 memxxx()

b. 如果需要序列化 / 反序列化,用 protobuf, json 等库,不要直接 dump 内存

④ 工程建议

a. 写工具类 / 测试代码时,如果需要内存填充,清零,二进制比较,需要确认对象是 POD

b. 代码评审时,看到 memcpy / memset 操作对象,需要确认必须是 POD

c. 如果对含 std::string 的 struct 做 memcpy(),会导致线上服务频繁 core dump 

相关文章:

  • 【PyQt5】PyQt5初探 - 一个简单的例程
  • 数据结构-排序-排序的七种算法(2)
  • Google Android 14设备和应用通知 受限制的设置 出于安全考虑......
  • Office办公文档软件安装包2024版
  • Java复习Day25
  • 性能优化 - 案例篇:缓冲区
  • Vue-1-前端框架Vue基础入门之一
  • Redis 缓存穿透、缓存击穿、缓存雪崩详解与解决方案
  • c++学习值---模版
  • Java设计模式详解:策略模式(Strategy Pattern)
  • [蓝桥杯]缩位求和
  • Odoo 中SCSS的使用指南
  • Vue框架2(vue搭建方式2:利用脚手架,ElementUI)
  • Python Day39 学习(复习日志Day4)
  • 鸿蒙OSUniApp PWA开发实践:打造跨平台渐进式应用#三方框架 #Uniapp
  • 用户资产化视角下开源AI智能名片链动2+1模式S2B2C商城小程序的应用研究
  • (9)-Fiddler抓包-Fiddler如何设置捕获Https会话
  • ACL基础配置
  • python爬虫:RoboBrowser 的详细使用
  • 雷达中实信号与复信号
  • 云南网站优化/seo怎么做最佳
  • 网站更改关键词/企业网站seo托管怎么做
  • 做分析图用的地图网站/网站优化软件费用
  • 北京网站建设icp有限公司/全球网站流量排名查询
  • 广州网站建设公司排名/上海优化公司选哪个
  • 做网站卖假名牌违法吗/廊坊seo排名外包