1、报告框架分类
- xUnit style xml报告
- mvn surefire插件的html报告
- Allure2多语言测试报告
2、生成测试报告
2.1 xUnit style xml报告
所有XUnit的测试报告都适用,如Java的Junit,Python的pytest等
- 1)现有如下测试类
Junit4DemoTest
package junit4demo;
import org.junit.*;
import org.junit.runners.MethodSorters;
import static org.junit.Assert.assertTrue;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class Junit4DemoTest {
@BeforeClass
public static void beforeAllTestCase(){
System.out.println("我是@BeforeClass,我是第一步");
}
@AfterClass
public static void afterAllTestCase(){
System.out.println("我是@AfterClass,我是最后一步");
}
@Before
public void beforeTestCase(){
System.out.println("我是@Before,用例执行前先到我这");
}
@After
public void afterTestCase(){
System.out.println("我是@After,用例执行后到我这");
}
@Test
public void testDemoC(){
System.out.println("testDemoC");
assertTrue(true);
}
@Test
public void testDemoA(){
System.out.println("testDemoA");
assertTrue(false );
}
@Test
public void testDemoB(){
System.out.println("testDemoB");
assertTrue(true );
}
}
2)用mvn test -Dtest=Junit4DemoTest
执行Junit4DemoTest
测试类,执行完毕之后我们可以在target.surefire-report.Surefile suite
路径下看到文件TEST-junit4demo.Junit4DemoTest.xml
,这就是xUnit style xml报告
testsuite
中显示了测试类的名称,执行时间,执行的用例数,错误数,跳过数和失败数:property
定义了当时执行的环境,Java和Java库的版本等:testcase
展示了测试类的名称以及测试类的执行时间- 如果有失败的用例,会将fail的信息打印在failure标签下,并将失败前的运行结果打印出来:
- 完整的报告信息如下:
<?xml version="1.0" encoding="UTF-8"?> <testsuite xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report.xsd" name="junit4demo.Junit4DemoTest" time="0.234" tests="3" errors="0" skipped="0" failures="1"> <properties> <property name="gopherProxySet" value="false"/> <property name="awt.toolkit" value="sun.lwawt.macosx.LWCToolkit"/> <property name="file.encoding.pkg" value="sun.io"/> <property name="java.specification.version" value="1.8"/> <property name="sun.cpu.isalist" value=""/> <property name="sun.jnu.encoding" value="UTF-8"/> <property name="java.class.path" value="/Users/qinzhen/Documents/TestDev/MyTraining/XUnit/target/test-classes:/Users/qinzhen/Documents/TestDev/MyTraining/XUnit/target/classes:/Users/qinzhen/.m2/repository/org/testng/testng/6.14.3/testng-6.14.3.jar:/Users/qinzhen/.m2/repository/com/beust/jcommander/1.72/jcommander-1.72.jar:/Users/qinzhen/.m2/repository/org/apache-extras/beanshell/bsh/2.0b6/bsh-2.0b6.jar:/Users/qinzhen/.m2/repository/org/junit/jupiter/junit-jupiter-engine/5.5.2/junit-jupiter-engine-5.5.2.jar:/Users/qinzhen/.m2/repository/org/apiguardian/apiguardian-api/1.1.0/apiguardian-api-1.1.0.jar:/Users/qinzhen/.m2/repository/org/junit/platform/junit-platform-engine/1.5.2/junit-platform-engine-1.5.2.jar:/Users/qinzhen/.m2/repository/org/opentest4j/opentest4j/1.2.0/opentest4j-1.2.0.jar:/Users/qinzhen/.m2/repository/org/junit/platform/junit-platform-commons/1.5.2/junit-platform-commons-1.5.2.jar:/Users/qinzhen/.m2/repository/org/junit/jupiter/junit-jupiter-api/5.5.2/junit-jupiter-api-5.5.2.jar:/Users/qinzhen/.m2/repository/org/junit/platform/junit-platform-runner/1.5.1/junit-platform-runner-1.5.1.jar:/Users/qinzhen/.m2/repository/org/junit/platform/junit-platform-launcher/1.5.1/junit-platform-launcher-1.5.1.jar:/Users/qinzhen/.m2/repository/org/junit/platform/junit-platform-suite-api/1.5.1/junit-platform-suite-api-1.5.1.jar:/Users/qinzhen/.m2/repository/junit/junit/4.12/junit-4.12.jar:/Users/qinzhen/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar:/Users/qinzhen/.m2/repository/org/junit/jupiter/junit-jupiter/5.5.0-M1/junit-jupiter-5.5.0-M1.jar:/Users/qinzhen/.m2/repository/org/junit/jupiter/junit-jupiter-params/5.5.0-M1/junit-jupiter-params-5.5.0-M1.jar:/Users/qinzhen/.m2/repository/org/apache/maven/surefire/surefire-testng-utils/2.22.0/surefire-testng-utils-2.22.0.jar:/Users/qinzhen/.m2/repository/org/apache/maven/surefire/surefire-grouper/2.22.0/surefire-grouper-2.22.0.jar:"/> <property name="java.vm.vendor" value="Oracle Corporation"/> <property name="sun.arch.data.model" value="64"/> <property name="java.vendor.url" value="http://java.oracle.com/"/> <property name="user.timezone" value=""/> <property name="java.vm.specification.version" value="1.8"/> <property name="os.name" value="Mac OS X"/> <property name="user.country" value="CN"/> <property name="sun.java.launcher" value="SUN_STANDARD"/> <property name="sun.boot.library.path" value="/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home/jre/lib"/> <property name="sun.java.command" value="/Users/qinzhen/Documents/TestDev/MyTraining/XUnit/target/surefire/surefirebooter7582774321603719140.jar /Users/qinzhen/Documents/TestDev/MyTraining/XUnit/target/surefire 2019-10-15T08-12-59_318-jvmRun1 surefire5421147855410474454tmp surefire_03665361789485499624tmp"/> <property name="test" value="Junit4DemoTest"/> <property name="surefire.test.class.path" value="/Users/qinzhen/Documents/TestDev/MyTraining/XUnit/target/test-classes:/Users/qinzhen/Documents/TestDev/MyTraining/XUnit/target/classes:/Users/qinzhen/.m2/repository/org/testng/testng/6.14.3/testng-6.14.3.jar:/Users/qinzhen/.m2/repository/com/beust/jcommander/1.72/jcommander-1.72.jar:/Users/qinzhen/.m2/repository/org/apache-extras/beanshell/bsh/2.0b6/bsh-2.0b6.jar:/Users/qinzhen/.m2/repository/org/junit/jupiter/junit-jupiter-engine/5.5.2/junit-jupiter-engine-5.5.2.jar:/Users/qinzhen/.m2/repository/org/apiguardian/apiguardian-api/1.1.0/apiguardian-api-1.1.0.jar:/Users/qinzhen/.m2/repository/org/junit/platform/junit-platform-engine/1.5.2/junit-platform-engine-1.5.2.jar:/Users/qinzhen/.m2/repository/org/opentest4j/opentest4j/1.2.0/opentest4j-1.2.0.jar:/Users/qinzhen/.m2/repository/org/junit/platform/junit-platform-commons/1.5.2/junit-platform-commons-1.5.2.jar:/Users/qinzhen/.m2/repository/org/junit/jupiter/junit-jupiter-api/5.5.2/junit-jupiter-api-5.5.2.jar:/Users/qinzhen/.m2/repository/org/junit/platform/junit-platform-runner/1.5.1/junit-platform-runner-1.5.1.jar:/Users/qinzhen/.m2/repository/org/junit/platform/junit-platform-launcher/1.5.1/junit-platform-launcher-1.5.1.jar:/Users/qinzhen/.m2/repository/org/junit/platform/junit-platform-suite-api/1.5.1/junit-platform-suite-api-1.5.1.jar:/Users/qinzhen/.m2/repository/junit/junit/4.12/junit-4.12.jar:/Users/qinzhen/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar:/Users/qinzhen/.m2/repository/org/junit/jupiter/junit-jupiter/5.5.0-M1/junit-jupiter-5.5.0-M1.jar:/Users/qinzhen/.m2/repository/org/junit/jupiter/junit-jupiter-params/5.5.0-M1/junit-jupiter-params-5.5.0-M1.jar:/Users/qinzhen/.m2/repository/org/apache/maven/surefire/surefire-testng-utils/2.22.0/surefire-testng-utils-2.22.0.jar:/Users/qinzhen/.m2/repository/org/apache/maven/surefire/surefire-grouper/2.22.0/surefire-grouper-2.22.0.jar:"/> <property name="sun.cpu.endian" value="little"/> <property name="user.home" value="/Users/qinzhen"/> <property name="user.language" value="zh"/> <property name="java.specification.vendor" value="Oracle Corporation"/> <property name="java.home" value="/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home/jre"/> <property name="basedir" value="/Users/qinzhen/Documents/TestDev/MyTraining/XUnit"/> <property name="file.separator" value="/"/> <property name="line.separator" value=" "/> <property name="java.vm.specification.vendor" value="Oracle Corporation"/> <property name="java.specification.name" value="Java Platform API Specification"/> <property name="java.awt.graphicsenv" value="sun.awt.CGraphicsEnvironment"/> <property name="surefire.real.class.path" value="/Users/qinzhen/Documents/TestDev/MyTraining/XUnit/target/surefire/surefirebooter7582774321603719140.jar"/> <property name="sun.boot.class.path" value="/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home/jre/lib/sunrsasign.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home/jre/classes"/> <property name="sun.management.compiler" value="HotSpot 64-Bit Tiered Compilers"/> <property name="java.runtime.version" value="1.8.0_221-b11"/> <property name="user.name" value="qinzhen"/> <property name="path.separator" value=":"/> <property name="os.version" value="10.14.5"/> <property name="java.endorsed.dirs" value="/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home/jre/lib/endorsed"/> <property name="java.runtime.name" value="Java(TM) SE Runtime Environment"/> <property name="file.encoding" value="UTF-8"/> <property name="java.vm.name" value="Java HotSpot(TM) 64-Bit Server VM"/> <property name="localRepository" value="/Users/qinzhen/.m2/repository"/> <property name="java.vendor.url.bug" value="http://bugreport.sun.com/bugreport/"/> <property name="java.io.tmpdir" value="/var/folders/55/lg_7qtv13d93hk9v7kjkn_p80000gn/T/"/> <property name="java.version" value="1.8.0_221"/> <property name="user.dir" value="/Users/qinzhen/Documents/TestDev/MyTraining/XUnit"/> <property name="os.arch" value="x86_64"/> <property name="java.vm.specification.name" value="Java Virtual Machine Specification"/> <property name="java.awt.printerjob" value="sun.lwawt.macosx.CPrinterJob"/> <property name="sun.os.patch.level" value="unknown"/> <property name="java.library.path" value="/Users/qinzhen/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:."/> <property name="java.vm.info" value="mixed mode"/> <property name="java.vendor" value="Oracle Corporation"/> <property name="java.vm.version" value="25.221-b11"/> <property name="java.ext.dirs" value="/Users/qinzhen/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java"/> <property name="sun.io.unicode.encoding" value="UnicodeBig"/> <property name="java.class.version" value="52.0"/> </properties> <testcase name="testDemoA on testDemoA(junit4demo.Junit4DemoTest)" classname="junit4demo.Junit4DemoTest" time="0.007"> <failure type="java.lang.AssertionError">java.lang.AssertionError at junit4demo.Junit4DemoTest.testDemoA(Junit4DemoTest.java:40) </failure> <system-out><![CDATA[我是@BeforeClass,我是第一步 我是@Before,用例执行前先到我这 testDemoA 我是@After,用例执行后到我这 ]]></system-out> </testcase> <testcase name="testDemoB on testDemoB(junit4demo.Junit4DemoTest)" classname="junit4demo.Junit4DemoTest" time="0.001"/> <testcase name="testDemoC on testDemoC(junit4demo.Junit4DemoTest)" classname="junit4demo.Junit4DemoTest" time="0"/> </testsuite>
2.2 mvn surefire插件的html报告
mvn site
生成项目网站的基础配置,然后执行mvn surefire-report:report
就可以生成对应的报告:
2.3 Allure2测试报告
2.3.1 allure2是什么?
- 先看allure2官方的解释 这是下一代的Allure Report,一种灵活的轻量级多语言测试报告工具,可以添加步骤,附件,参数等
2.3.2 allure2的安装
- 对于不同的系统,如Linux,Mac和Windows的安装,在官网上给出了具体方法:
- 这里以Mac系统演示,直接在终端执行命令
brew install allure
后执行allure
,看到如下展示就说明安装成功了,里面展示了allure的各种命令参数: 或者使用allure --version
命令也可以确认安装成功
2.3.3 allure2简易报告的生成
- 再来看官网给的教程:
- 先在IDE中执行测试,在
target/surefire-reports
目录下生成对应的xml报告- 再执行
allure serve
命令
- 效果展示
在我的
target/surefire-reports
目录下有两个测试类生成的xml报告 执行完allure serve /Users/qinzhen/Documents/TestDev/MyTraining/XUnit/target/surefire-reports
命令后会自动打开如下页面: - 报告分析
- Overview :首页
Overview
是个总览,总体展示分别执行了哪些测试类,执行的pass、fail结果如何等 - Categories : 将失败的结果进行一个分类
- Suites:展示所有用例的具体执行情况 Graphs : 图形化展示基本数据
- Timeline : 时间轴,可拉动进行测试回顾(这里引用官方的图片,演示项目执行太少,效果不明显~)
- Behaviors : 以不同特征对测试用例进行分组
- Packages :展示不同用例所处的包
- Overview :首页
3、allure详细报告生成
3.1 allure的工作机制
- 在测试框架中添加allure的依赖和配置
- 执行测试
- 生成allure-results
- allure generate allure-results -o allure-report
3.2 生成allure-results
allure几乎支持所有语言,在官网中也给出了各种语言框架的报告生成方式,如下图:
这里就以Java的Junit4框架为例 1)pom中添加依赖、插件和所需属性<properties>
<aspectj.version>1.8.10</aspectj.version>
</properties>
<dependencies>
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-junit4</artifactId>
<version>LATEST_VERSION</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20</version>
<configuration>
<testFailureIgnore>false</testFailureIgnore>
<argLine>
-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
</argLine>
<properties>
<property>
<name>listener</name>
<value>io.qameta.allure.junit4.AllureJunit4</value>
</property>
</properties>
</configuration>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
...
注:allure-junit4依赖的版本LATEST_VERSION可从官网上查看:
2)再执行mvn clean test
,执行完之后可以看到在项目中多了一个文件夹allure-results
3.3 注解特性
3.3.1 注解概览
官网上有如下一段话:
Java的注解和特性可用于allure的主要特性,并列举了如下一些注解特性:注解 | 说明 |
---|---|
@DisplayName | 设置用例展示名称 |
@Description | 描述 |
@Step | 设置步骤,完成步骤描述 |
@Attachments | 添加附件 |
Links: @Link、@Issue、@TmsLink | 将测试链接到某些资源,设置bug编号 ,设置用例编号 |
@Severity | 设置bug等级,blocker、caitical、minor、normal、trivial |
-
@Link,官网上给出了这样的说明
从官网给出的说明和举例可以看到通过@Link可以设置链接地址,但是需要额外的配置 例子中第一个@Link
,目前我的理解是展示需要链接的地址,无其他实际作用(可能还有其他作用,目前知识储备还不够,待探索) 例子中第二个@Link
就是设置需要链接的具体位置和类型,name
中填写的就是配置中{}
替换的内容(可以在配置中去掉{},这样name就可以单存的作为一个超链接的名字使用) 上面说了需要配置,没错!需要在test同级目录下创建Test Resources Root
类型的文件夹resources
并创建配置文件allure.properties
allure.results.directory=target/allure-results allure.link.mylink.pattern=http://xxx.com/ allure.link.issue.pattern=https://example.org/issue/{} allure.link.tms.pattern=https://example.org/tms/{}
==语言描述起来比较晦涩,下面实操展示部分就会清晰很多==
-
@Severity,官网上并没有直接说明Severity的几种等级,我们在IED中调用此接口时可以通过代码提示看到如下几个等级
3.3.2 实操展示
1)基本注解与@Link
- 给用例testDemoA加上注解
@DisplayName
、@Description
、@Link
、@Issue
、@Severity
- 在test同级目录下创建
Test Resources Root
类型的文件夹resources
并创建配置文件allure.properties
mvn clean test
->allure serve allure-results
后生成测试报告 由报告可看出注解带来的变化呈现: 点击bugAddress,就会直接跳转到我设置好的项目地址中:
2)@Step步骤展示
- 新建
login
方法并加入@Step
注解,命名为"login step";再在方法testDemoA
中调用两次方法login
: 测试结果: 从测试结果中可以看到,allure报告会把对应的方法调用执行步骤打印出来
3)@Attachment截图
官网上对于截图功能给出了两种方法,@Attachment
注解和Allure.addAttachment
API,这里用API来做演示
- 在login()方法中加入截图: 测试结果: 从测试结果可以看到每一次执行login功能时都会保存截图,这样在做UI自动化的时候可以设置监听,当用例失败时进行截图或者在关键步骤上设置截图,最终展现在测试报告中以方便测试结果分析
3.4 动态生成测试步骤
可以在用例中动态加入步骤,实际应用可以插入日志信息进行打印
3.5 Jenkins结合
待在Jenkins章节部分进行补充
4、链接地址
allure官方GitHub:
github.com/allure-fram…
github.com/allure-fram…
allure2官方GitHub: github.com/allure-fram…
allure2官方文档:docs.qameta.io/allure/#_ab…