JUnit5的条件测试、嵌套测试、重复测试

本书作者:测试开发刚哥,文章版权归个人所有,未经授权请勿转载。 条件测试 JUnit5支持条件注解,根据布尔值判断是否执行测试。 自定义条件 @EnabledIf和@DisabledIf注解用来设置自定义条件,示例: @Test @EnabledIf("customCondition") void enabled() { // ... } @Test @DisabledIf("customCondition") void disabled() { // ... } boolean customCondition() { return true; } 其中customCondition()方法用来返回布尔值,它可以接受一个ExtensionContext类型的参数。如果定义在测试类外部,那么需要是static方法。 内置条件 JUnit5的org.junit.jupiter.api.condition包中内置了一些条件注解。 操作系统条件 @EnabledOnOs和DisabledOnOs,示例: @Test @EnabledOnOs(MAC) void onlyOnMacOs() { // ... } @TestOnMac void testOnMac() { // ... } @Test @EnabledOnOs({ LINUX, MAC }) void onLinuxOrMac() { // ... } @Test @DisabledOnOs(WINDOWS) void notOnWindows() { // ... } @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Test @EnabledOnOs(MAC) @interface TestOnMac { } JRE条件 ...

端到端自动化的开源框架

本书作者:测试开发刚哥,文章版权归个人所有,未经授权请勿转载。 什么是Playwright? Playwright是一个开源框架,用于对Web应用进行端到端测试。 什么是端到端测试? 这里的“端”,不是指A模块或B模块,而是可以理解为从前端到后端。举个例子,对于登录功能来说,如果只测前端,那么测试范围就是前端页面,可能会对后端接口进行mock。如果只测后端,那么测试范围就是后端接口等。而端到端呢,就是前端输入用户名密码,点击登录,与后端交互,查询数据库,鉴权,后端返回登录成功,前端进行页面跳转。端到端测试,可以理解为全流程测试,也可以理解为模拟用户场景测试。 Playwright框架特点 官方网站首页:https://playwright.dev/python/ 总结下重点,一是跨浏览器、跨平台、跨语言;二是自动等待;三是多用户场景测试;四是只需要一次登录;五是可以录制脚本。 快速入门 在官网的顶部菜单可以切换不同编程语言的教程: 本文及后续文章均选择Python。 安装 安装Python的Playwright,这里结合了pytest: pip install pytest-playwright 成功后安装浏览器: playwright install 这里也可以不安装浏览器,而是在脚本里面指定现有浏览器路径。 示例 test_example.py import re from playwright.sync_api import Page, expect def test_has_title(page: Page): page.goto("https://playwright.dev/") # Expect a title "to contain" a substring. expect(page).to_have_title(re.compile("Playwright")) def test_get_started_link(page: Page): page.goto("https://playwright.dev/") # Click the get started link. page.get_by_role("link", name="Get started").click() # Expects page to have a heading with the name of Installation. expect(page.get_by_role("heading", name="Installation")).to_be_visible() 执行pytest后默认会选择chrome在headless模式下运行,可以通过日志观察运行过程。 更新命令: pip install pytest-playwright playwright -U 编写测试 访问url: ...

JMeter元件作用域实践指南

本书作者:测试开发刚哥,文章版权归个人所有,未经授权请勿转载。 从一个问题说起 对于以下测试脚本: 为了能调用进入房间接口,需要从考场接口获取考场token。为了调用考场接口,需要从登陆接口获取登陆token。元件说明如下: 学生登录,提取登录${token}传入下个接口参数。 添加HTTP Header Manager: 考场token,提取考场${exam_token}传入下个接口参数。 添加HTTP Header Manager: 进入房间 貌似挺合理,HTTP Header Manager会给下方的接口添加请求头,运行结果真的如我们所料么? 运行顺序 在回答这个问题之前,有必要搞懂JMeter元件的运行顺序,它是由2 个维度来决定的:从上往下和元件类型。 从上往下,即目录树从上往下。元件类型,分为3类: 线程组、逻辑控制器。 取样器。 配置元件、前置处理器、定时器、后置处理器、断言、监听器。 它们的运行顺序如下: 配置元件(如果存在) 前置处理器(如果存在) 定时器(如果存在) 取样器(如果存在) 后置处理器(如果存在且取样器的结果不为空) 断言(如果存在且取样器的结果不为空) 监听器(如果存在且取样器的结果不为空) 换句话说,假设我们新建了1个线程,想用这个线程去发请求。 第一步,初始化配置,比如参数化、设置Header、Cookie等,用到配置元件。 第二步,可能需要给线程加点参数,比如用户参数,用到前置处理器。 第三步,在发送请求前可能会等待一段时间,用到定时器。 第四步,发送请求,用到取样器。 第五步,可能需要提取响应数据,比如正则表达式提取器、JMESPath提取器,用到后置处理器。 第六步,验证结果符合预期,用到断言。 第七步,查看请求响应数据和测试结果,用到监听器。 实践指南 对于以下所列元件: JMeter会按以下步骤运行: 线程组(如果有多个线程组可以在测试计划设置是顺序执行还是同时执行) 简单控制器(父节点) HTTP Cookie管理器(配置元件) 用户参数(前置处理器) Synchronizing Timer(定时器) HTTP 请求1(取样器) 正则表达式提取器(后置处理器) 响应断言(断言) HTTP Cookie管理器(配置元件) 用户参数(前置处理器) Synchronizing Timer(定时器) HTTP 请求2(取样器) 正则表达式提取器(后置处理器) 响应断言(断言) HTTP 请求3(取样器) 察看结果树(严格来讲是与第 6 步并行,也就是取样器之后) 作用域 其中有个观察作用域实际效果的关键元件:HTTP请求2,它的前后并没有元件,但是也被作用上了。在JMeter中,同一层级的元件具有相同的作用域! ...

JUnit5的Tag、Filter、Order、Lifecycle

本书作者:测试开发刚哥,文章版权归个人所有,未经授权请勿转载。 Tag JUnit5可以使用@Tag注解给测试类和测试方法打tag,这些tag能用来在执行时进行过滤,它跟group有点类似。 tag应该遵循以下规则: 不能为null或者为空。 不能包含空格。 不能包含ISO控制字符。 不能包含保留字符:, ( ) & | ! 示例代码: import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @Tag("fast") @Tag("model") class TaggingDemo { @Test @Tag("taxes") void testingTaxCalculation() { } } @Tag还可以通过元注解和组合注解,实现自定义注解,参考: https://dongfanger.gitee.io/blog/JUnit/002-JUnit5%E6%B3%A8%E8%A7%A3%E5%AD%A6%E4%B9%A0%E6%8C%87%E5%BC%95.html#id2 Filter 打好了tag后,在执行时可以进行过滤,比如Maven配置: <!-- ... --> <build> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> <configuration> <groups>acceptance | !feature-a</groups> <excludedGroups>integration, regression</excludedGroups> </configuration> </plugin> </plugins> </build> <!-- ... --> groups用来指定包含哪些tag,excludedGroups用来指定排除哪些tag。 Order JUnit5默认使用了某种算法来确定test方法的执行顺序。我们可以通过@TestMethodOrder进行自定义,既可以使用内置类,也可以使用实现了MethodOrderer接口的类。 内置类如下: DisplayName 按DisplayName的字母数字顺序 OrderAnnotation 通过@Order注解指定顺序 Random 随机顺序 Alphanumeric 按test方法名和参数列表的字母数字顺序 示例: ...

send_keys报错element_not_interactable

这两天要在阿里云日志中操作UI,以输入关键字搜索日志。

SpringBoot接入JaCoCo实践教程

本书作者:测试开发刚哥,文章版权归个人所有,未经授权请勿转载。 静态接入和动态接入 SpingBoot可以通过2种方式接入JaCoCo:Maven和Agent。Maven方式是静态接入,在编译时计算代码覆盖率。Agent方式是动态接入,服务启起来以后,能实时根据代码命中情况计算代码覆盖率。 教程代码已上传开源项目:https://github.com/dongfanger/mini Maven pom.xml添加依赖: <dependency> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.7</version> </dependency> 添加配置: <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${project.parent.version}</version> </plugin> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.7</version> <executions> <execution> <id>default-prepare-agent</id> <goals> <goal>prepare-agent</goal> </goals> </execution> <execution> <id>default-report</id> <goals> <goal>report</goal> </goals> </execution> </executions> </plugin> </plugins> </build> 点击maven的install: target/site/jacoco目录下就生成了覆盖率报告: Agent 下载jacoco文件后解压,提取2个文件: 使用命令启动SpringBoot,启动参数添加-javaagent: java -javaagent:jacoco/jacocoagent.jar -jar target/mini-0.0.1-SNAPSHOT.jar 此时会生成1个jacoco.exec文件,这个文件就是覆盖率数据文件,采用以下命令根据数据文件生成HTML报告: java -jar jacoco/jacococli.jar report jacoco.exec --classfiles ./target/classes/ --sourcefiles ./src/main/java/ --html ./report 接下来就来验证动态特性。把report目录和jacoco.exec都删了,因为jacoco每次部署只能分析一次。把服务停掉后,重新启动。这一次不直接分析,而是先用postman调一下接口: 然后再分析一把: ...

把RPC包进事务的暗坑

本书作者:测试开发刚哥,文章版权归个人所有,未经授权请勿转载。 # 方式:把判断放进 SQL,一条语句的原子性 rows = db.execute(""" UPDATE pay_record SET status = 'PAID' WHERE order_no = ? AND status = 'INIT' """, order_no) if rows == 0: return "已处理" # 别人改过了,我不是第一个 grant_coupon(order_no) # 只有改成功的那个才发券 return "success" grant_coupon失败会发生什么? 券永久丢失,该发没发,资损。 第一次请求: UPDATE status: INIT → PAID ✅ 已提交,改不回去了 grant_coupon(order_no) ❌ 抛异常 / 超时 / 下游挂了 第二次请求: rows = db.execute("UPDATE ... WHERE status = 'INIT'") # status已是PAID # rows == 0 return "已处理" # ← 被自己的幂等逻辑拦住,不会执行grant_coupon 包进一个事务能解决吗 把update和grant_coupon这两个操作,包进一个事务里,要么同时执行,要么同时回滚,是不是就解决了? ...

JMeter英文版界面介绍

JMeter的界面虽然不华丽,但是使用起来还是很便利。本文将基于英文版界面对整个可视区域进行介绍,如果想看中文版,请在菜单栏点击Choose Language切换:

JUnit5编写基本测试

JUnit5的测试不是通过名称,而是通过注解来标识的。

webdriver使用已打开过的chrome

基本功能: