一、What is Allure Report?
Allure Report是一个生成漂亮且易于阅读的测试报告的工具。它能够将测试结果和测试日志以一种简洁的方式呈现出来,支持多种编程语言和测试框架,如Java、Ruby、Python和C#等语言以及TestNG、JUnit和Pytest等框架。Allure Report对于提高测试效率和后续问题定位都非常有帮助。
二、Features of Allure Report
使用Allure Report有以下几个优点和特点:
1、美观、易读:Allure Report的页面效果非常精美,整个测试报告看起来是非常直观且易于理解的。
2、灵活、易扩展:Allure Report支持多种编程语言和测试框架,而且还提供接口方便用户自定义插件。
3、历史报告:Allure Report支持历史记录,当运行了多个测试套件时,用户可以轻松地查看哪些测试用例失败或者哪些测试用例的性能不佳。
4、趋势分析:Allure Report也提供了趋势分析功能,用户可以根据前几次测试数据来分析软件的稳定性和改进方向。
三、How to Generate Allure Report?
使用Allure Report,需要以下几个步骤:
1、安装Allure Report:可以使用命令行安装,也可以使用IDE插件进行安装。
npm install -g allure-commandline
2、集成Allure Report到测试框架中:Allure Report支持多种编程语言和测试框架,集成方式各不相同。
下面以Java语言和TestNG框架为例:
//pom.xml文件中添加以下配置:
<dependencies>
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-testng</artifactId>
<version>2.0-BETA16</version>
<scope>test</scope>
</dependency>
</dependencies>
//TestListener.java文件中添加以下内容:
public class TestListener extends TestListenerAdapter {
@Override
public void onTestSuccess(ITestResult result) {
saveTextLog(getTestMethodName(result) + " Passed successfully!");
}
@Override
public void onTestFailure(ITestResult result) {
saveTextLog(getTestMethodName(result) + " Failed!");
saveScreenshotPNG(driver);
}
@Override
public void onTestSkipped(ITestResult result) {
saveTextLog(getTestMethodName(result) + " Skipped!");
}
}
//TestBase.java文件中添加以下内容:
@Listeners({TestListener.class})
public class TestBase{
//code
}
3、运行测试用例并生成测试报告:在项目根目录下运行以下命令即可生成测试报告
mvn clean test
allure serve allure-results
四、Customize Allure Report
Allure Report同样提供自定义插件的功能。用户可以根据自身需求添加额外的数据到测试报告中,比如Jenkins集成、执行时间、测试结果分类等。
下面以添加分类数据为例:
//pom.xml中添加以下配置:
<dependencies>
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-testng</artifactId>
<version>2.0-BETA16</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-java-commons</artifactId>
<version>2.0-BETA16</version>
</dependency>
</dependencies>
//Category.java文件:
public enum Category {
SEARCH("Search"), LOGIN("Login"), CHECKOUT("Checkout"), PROMO("Promo");
private String name;
Category(String name) {
this.name = name;
}
public String get() {
return name;
}
}
//CategoryAnnotation.java文件:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
@Retention(RetentionPolicy.RUNTIME)
@Target({METHOD, TYPE})
public @interface CategoryAnnotation {
Category[] value();
String[] component() default {};
}
//TestListener.java中添加以下内容:
public void setCategories(ITestResult result, Description description) {
String[] categories = Arrays.stream(description.getAnnotations())
.filter(a -> a.annotationType().equals(CategoryAnnotation.class))
.map(a -> ((CategoryAnnotation) a).value())
.flatMap(Arrays::stream).map(Category::get).toArray(String[]::new);
if (categories.length != 0) {
result.getTestContext().setAttribute("categories", categories);
}
}
/***
* Description: 具体执行测试
* @param result
*/
@Override
public void onTestStart(ITestResult result) {
String name = getTestMethodName(result);
Category[] category = getCategory(result);
StringBuilder builder = new StringBuilder();
if (category != null) {
builder.append("[");
for (int i = 0; i < category.length; i++) {
builder.append(category[i].get());
if (i < category.length - 1) {
builder.append(",");
}
}
builder.append("] ");
}
builder.append(name);
log.info("Start test:" + builder.toString());
Step step = new Step();
step.setName(builder.toString());
step.setStatus(Status.PASSED);
Allure.getLifecycle().startStep(UUID.randomUUID().toString(),step);
}
/***
* Description:获取Method的category[Array]
* @param result
* @return
*/
public Category[] getCategory(ITestResult result) {
Description description = getDescription(result);
if (description != null) {
List
annotationList = getDeclaredAnnotations(description);
for (Annotation a : annotationList) {
if (a instanceof CategoryAnnotation) {
return ((CategoryAnnotation) a).value();
}
}
}
return null;
}
/***
* Description:获取到当前的Case的Description
* @param result
* @return
*/
public Description getDescription(ITestResult result) {
Description description = null;
try {
Object instance = result.getInstance();
if (instance instanceof ITestCase) {
description = ((ITestCase) instance).getDescription(result);
} else {
Field f = result.getClass().getDeclaredField("m_description");
f.setAccessible(true);
description = (Description) f.get(result);
}
} catch (Exception e) {
e.printStackTrace();
}
return description;
}
/**
* 获取调用的所有注解
* @param description
* @return
*/
private List
getDeclaredAnnotations(Description description) {
List
classAnnotations = Lists.newArrayList();
Class clazz = description.getTestClass();
if (clazz != null) {
classAnnotations.addAll(Arrays.asList(clazz.getDeclaredAnnotations()));
classAnnotations.addAll(getDeclaredAnnotations(Description.createSuiteDescription(clazz)));
}
return ImmutableList.copyOf(Iterables.concat(
Arrays.asList(description.getAnnotations()),
classAnnotations));
}
//运行测试用例:在@Test方法或@Test Class上加入@CategoryAnnotation注释即可。
@CategoryAnnotation(value = { Category.LOGIN, Category.CHECKOUT }, component = {"UI"})
@Test
public void checkDefaultLoginRun() {
......
}
五、Conclusion
Allure Report是一个非常棒的测试报告工具,由于其美观易读、易于扩展、历史报告以及趋势分析等特点,在软件测试中使用较为广泛。希望大家能够了解Allure Report,掌握使用方法,提高测试效率和进一步提升产品质量。