Selenium自动化测试,使用Jenkins自动化集成Maven工程, 想要生成直观简洁的测试报告可以使用Allure插件。
Allure介绍
Allure是一款非常轻量级并且非常灵活的开源测试报告生成框架。它简单易用,易于集成,并且支持绝大多数测试框架, 例如TestNG、Pytest、JUint等。
本文主要结合Jenkins与Maven、Allure集成做详细介绍。
环境准备
1、安装Jenkins
Jenkins 是基于Java开发的一种持续集成工具,所以首先必须搭建好Java环境(自行百度)。然后配置好Tomcat。
a、在https://jenkins.io/上下载Jenkins,把下载的jenkins.war放在tomcat的webapps的目录下,进入到tomcat的bin目录下,双击startup.bat文件启动tomcat。启动后,在浏览器中访问Tomcat配置监听的IP端口,默认访问地址:http://localhost:8080/jenkins。
b、首次使用Jenkins需要输入密码,Windows下Jenkins登录密码在C:\Program Files (x86)\Jenkins\secrets目录下的initialAdminPassword文件中,复制其中的内容,把它copy到jenkins的密码输入框,点击下一步,配置账户密码,选择安装推荐插件或者手动选择都可以
c、全局工具配置
进入系统管理--全局工具配置,配置JDK、git、Maven
2、Allure 插件安装配置
a、进入Jenkins 系统管理---插件管理,在右侧的搜索框中直接搜索 allure,就可以看到 Allure Jenkins Plugin插件,点击安装。安装成功后,在已安装列表里查看到该插件的信息。
b、进入Jenkins 系统管理---全局工具设置,在全局工具设置的界面安装Allure,选择下载的插件版本,点击save保存。
自动化脚本准备
1、创建Maven工程
具体的内部代码实现,这里不再赘述。
a、配置pom.xml文件,添加Allure所需依赖包及插件
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-java-commons</artifactId>
<version>2.10.0</version>
<scope>compile</scope>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>APD-DemoCase-Automation.xml</suiteXmlFile>
</suiteXmlFiles>
<argLine>
-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar" -Dfile.encoding=UTF-8
</argLine>
</configuration>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
b、想要在打开的Allure测试报告里显示失败用例的截图和测试步骤,需要添加监听类
创建FailedStepListener类
使用Allure的@Attachment注解就可以在测试报告里显示附件。
这里首先获取执行的case的类的名称,然后与时间字符串拼接图片的名称以及图片的存储目录。如果目录不存在就自动创建。通过FileOutputStream流对象写入文件。
import io.qameta.allure.Attachment;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.testng.ITestResult;
import org.testng.TestListenerAdapter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import static com.cccis.util.GlobalSetting.SCREENSHOT_PATH;
public class FailedStepListener extends TestListenerAdapter {
@Override
public void onTestFailure(ITestResult result){
takeScreenshot(result);
}
@Attachment(value = "screenshot",type = "image/png")
public byte[] takeScreenshot(ITestResult result){
byte[] screenshotAs = ((TakesScreenshot)CommonTest.chrome_driver).getScreenshotAs(OutputType.BYTES);
String[] classNameArr = result.getTestClass().getName().split("\\.");
String className = classNameArr[classNameArr.length-1];
String methodName = result.getName();
String time = new SimpleDateFormat("_yyyyMMdd_HHmmss").format(new Date());
String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
String scrFolder = SCREENSHOT_PATH+date+"/"+className;
File dir = new File(scrFolder);
if(!dir.exists()){
dir.mkdirs();
}
String picPath = scrFolder+"/"+methodName+time+".png";
try (FileOutputStream out = new FileOutputStream(picPath)){
out.write(screenshotAs);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return screenshotAs;
}
}
代码((TakesScreenshot)CommonTest.chrome_driver).getScreenshotAs(OutputType.BYTES)里的chrome_driver通过CommonTest类传过来。
import org.apache.logging.log4j.Logger;
import org.openqa.selenium.WebDriver;
import org.testng.Assert;
import org.testng.ITestContext;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
public class CommonTest {
protected TestEnvSetup tes;
public static WebDriver chrome_driver;
protected Logger log;
protected String testcaseName;
protected SeleniumUtil seleUtilChrome;
protected ITestContext testContext = null;
@BeforeClass(alwaysRun = true)
public void setup(ITestContext testContext) {
testcaseName = this.getClass().getName();
tes = new TestEnvSetup(testcaseName);
log = tes.getLogger();
chrome_driver = tes.iniChromeDriver();
this.testContext = testContext;
seleUtilChrome = new SeleniumUtil(chrome_driver, log);
seleUtilChrome.keepOneWindow();
testContext.setAttribute("driver", chrome_driver);
}
@AfterClass(alwaysRun = true)
public void tearDown() {
if (chrome_driver != null) {
chrome_driver.close();
chrome_driver.quit();
} else {
Assert.fail("driver没有获得对象,退出操作失败");
}
}
}
基础类TestEnvSetup
package com.cccis.util;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.testng.ITestContext;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static com.cccis.util.GlobalSetting.*;
public class TestEnvSetup {
WebDriver ieDriver;
WebDriver chromeDriver;
WebDriver driver;
Logger log;
ITestContext testContext;
public TestEnvSetup(String testcaseName) {
log = LogManager.getLogger(testcaseName);
}
public WebDriver iniChromeDriver() {
ChromeOptions options = new ChromeOptions();
// // 通过配置参数禁止data;的出现
// options.addArguments("--user-data-dir=C:/Users/ccc/AppData/Local/Google/Chrome/User Data/Default");
Map<String, Object> setting = new HashMap<>();
setting.put("audiblePlaybacks", 0);
setting.put("hasHighScore", false);
setting.put("lastMediaPlaybackTime", 0.0);
setting.put("mediaPlaybacks", 0);
setting.put("significantPlaybacks", 0);
setting.put("visits", 1);
setting.put("visitsWithMediaTag", 0);
Map<String, Object> ip = new HashMap<>();
ip.put("last_modified", "13169187114098237");
ip.put("setting", setting);
Map<String, Object> media = new HashMap<>();
media.put("http://19*.168.200.**:****,*", ip);
Map<String, Object> exceptions = new HashMap<>();
exceptions.put("media_engagement", media);
Map<String, Object> plugins = new HashMap<>();
Map<String, Object> ip2 = new HashMap<>();
ip2.put("last_modified", "13169187019441329");
ip2.put("setting", 1);
plugins.put("http://19*.168.200.**:****,*", ip2);
exceptions.put("plugins", plugins);
Map<String, Object> contentSettings = new HashMap<>();
contentSettings.put("exceptions", exceptions);
Map<String, Object> profile = new HashMap<>();
profile.put("avatar_bubble_tutorial_shown", 2);
profile.put("avatar_index", 17);
profile.put("content_settings", contentSettings);
Map<String, Object> prefs = new HashMap<>();
prefs.put("profile", profile);
// chrome68 不需要设置
// options.setExperimentalOption("prefs", prefs);
// 通过配置参数删除稳定性和安全性会有所下降提示
options.addArguments("--start-maximized", "allow-running-insecure-content", "--test-type");
options.addArguments("disable-infobars");
System.setProperty("webdriver.chrome.driver", CHROME_DRIVER_PATH);
chromeDriver = new ChromeDriver(options);
// chromeDriver.manage().window().maximize();
chromeDriver.manage().timeouts().implicitlyWait(ELEMENT_TIMEOUT, TimeUnit.SECONDS);
SeleniumUtil.log(log,"启动测试浏览器为:[ Chrome ]");
return chromeDriver;
}
public Logger getLogger() {
return log;
}
}
testng.xml中添加监听
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="APD Demo UI Automation Testing" verbose="1" thread-count="1">
<test name="All Testcase" preserve-order="true">
<packages>
<package name="com.***.testcase.*"/>
</packages>
</test>
<listeners>
<!--<listener class-name="org.uncommons.reportng.HTMLReporter" />-->
<listener class-name="com.cccis.util.FailedStepListener"/>
</listeners>
</suite>
最后测试用例对应类继承CommonTest类即可
c、如果Allure report需要自动生成在指定目录(默认生成于项目的根路径下),需要在项目的resources目录下创建allure.properties文件,文件的内容:
allure.results.directory=target/allure-results
2、将上述工程上传至git(如何上传自行百度)
构建Jenkins任务
1、构建一个maven项目
a、新建一个构建任务,选择 构建一个maven项目,取名如AllureDemo,点击确定
构建项目的时候,Jenkins会根据项目名称在工作空间里面创建一个目录(目录名称同项目名称)
例如,Jenkins在自己本地时,目录路径:C:\Users\用户名.jenkins\jobs\AllureDemo。 Jenkins会自动编译里面的源码。
b、在配置界面,进行以下配置
c、点击保存会返回项目详情页面,可以看到显示allure测试报告的图标
d、点击左侧立即构建,完成后可以看到构建的信息,点击allure测试报告即可以看到allure测试报告
这里遇到一个坑,点击图中的小图标,打开Allure报告显示404。
原因:Jenkins系统管理--系统设置中,Jenkins Location的Jenkins URL设置不正确,修改正确即可。
2、查看Allure Report 测试报告
Allure Report 测试报告主要分为总览、类别、测试套、图表、时间刻度、功能、包。
总览 ,中展示了本次测试的测试用例数量,成功用例、失败用例、跳过用例的比例,测试环境信息,SUITES,FEATURES BY STORIES等基本信息,当与Jenkins做了持续置成后,TREND区域还将显示,历次测试的通过情况。
Suites 按脚本的目录结果展示本次所有的测试用例执行情况
Behaviors功能
Categories类别
Graphs图表