testng + reportng 测试结果邮件发送
2016-05-25 12:45
435 查看
其实大多数的时候我们的测试报告的发送可能都是结合Jenkins发送的,所以这方面更多的都是依赖于它,可是如果有的时候我们不需要Jenkins的时候,我们应该如何去处理这部分的内容呢
maven-surefire-plugin 这个插件主要是用于testng的。我们通过该插件,在对应的目录下
这里实际上就是reportng的测试报告的生成路径。但是我们想要通过邮件发送会很难,因为html的内容需要加在额外的css,以及js文件。而邮件实际上是不支持外部的css以及js文件的。
以上的内容我删除掉了部分property的内容。从这里我们就可以通过
下来看看我们生成html的代码吧。
以上中还少了个base_html的定义,因为那部分比较长,主要是一些css的定义,采用bootstrap中的部分css。
生成html后,实际如果写入到一个html中的话,就可以变成下图这样子了。
下来再来看看具体的发送邮件的代码吧
这里就是发送的邮件的方法了,可是又来问题了,我们需要在什么时候调用这个发送邮件的方法呢。一开始的想法是在
指明我们运行的阶段以及运行的java类就可以了。但是这里有两点需要注意
java类必须在目录 main/java下才行。不能够在test目录下。
如果testng的配置中没有增加
以上两点是需要注意的地方了。
项目情况
由于我们使用的是maven,所以我们主要来看看pom.xml的情况<plugin> <groupId>org.apache.maven.plugins</groupId><!--使用该插件设置TESTNG的配置文件位置--> <artifactId>maven-surefire-plugin</artifactId> <executions> <execution> <goals> <goal>test</goal> </goals> </execution> </executions> <version>2.19</version> <configuration> <properties> <property> <name>usedefaultlisteners</name> <value>false</value> </property> <property> <name>listener</name> <value>org.uncommons.reportng.HTMLReporter,org.uncommons.reportng.JUnitXMLReporter</value> </property> </properties> <suiteXmlFiles> <suitXmlFile>testSuits/seewotraining.xml</suitXmlFile> </suiteXmlFiles> <reportsDirectory>./target/${timestamp}</reportsDirectory> <systemPropertyVariables> <org.uncommons.reportng.escape-output>false</org.uncommons.reportng.escape-output> </systemPropertyVariables> </configuration> </plugin>
maven-surefire-plugin 这个插件主要是用于testng的。我们通过该插件,在对应的目录下
./target/${timestamp}生成我们的测试报告目录。我们可以看到这个目录的结构。
这里实际上就是reportng的测试报告的生成路径。但是我们想要通过邮件发送会很难,因为html的内容需要加在额外的css,以及js文件。而邮件实际上是不支持外部的css以及js文件的。
html的生成
所以就需要我们自己想办法来,既然这样子那我们就自己写一个html就可以了。那么我们要怎么才能够知道测试结果的情况呢,我们可以从这个文件里面获取到TEST-TestSuit.xml我们可以看看这个xml的内容
<?xml version="1.0" encoding="UTF-8"?> <testsuite xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report.xsd" name="TestSuite" time="78.567" tests="2" errors="0" skipped="0" failures="2"> <properties> <property name="java.runtime.name" value="Java(TM) SE Runtime Environment"/> <property name="sun.boot.library.path" value="C:\Program Files\Java\jdk1.8.0_11\jre\bin"/> <property name="java.vm.version" value="25.11-b03"/> <property name="java.vm.vendor" value="Oracle Corporation"/> <property name="maven.multiModuleProjectDirectory" value="E:\eclipseProject\SeewoTraining"/> <property name="java.vendor.url" value="http://java.oracle.com/"/> <property name="sun.cpu.isalist" value="amd64"/> </properties> <testcase name="login" classname="com.seewo.training.TestSeewoTraining" time="60.103"> <failure message="Timed out after 30 seconds waiting for visibility of Proxy element for: DefaultElementLocator 'By.xpath: //*[@id='username']' Build info: version: '2.53.0', revision: '35ae25b1534ae328c771e0856c93e187490ca824', time: '2016-03-15 10:43:46' System info: host: 'cvtpc-PC', ip: '127.0.0.1', os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.8.0_11' Driver info: org.openqa.selenium.chrome.ChromeDriver Capabilities [{applicationCacheEnabled=false, rotatable=false, mobileEmulationEnabled=false, chrome={chromedriverVersion=2.21.371459 (36d3d07f660ff2bc1bf28a75d1cdabed0983e7c4), userDataDir=C:\Users\cvtpc\AppData\Local\Temp\scoped_dir31352_25457}, takesHeapSnapshot=true, databaseEnabled=false, handlesAlerts=true, hasTouchScreen=false, version=47.0.2526.106, platform=XP, browserConnectionEnabled=false, nativeEvents=true, acceptSslCerts=true, locationContextEnabled=true, webStorageEnabled=true, browserName=chrome, takesScreenshot=true, javascriptEnabled=true, cssSelectorsEnabled=true}] Session ID: c0c126ea4d4db0e1c3e2ca8352645830" type="org.openqa.selenium.TimeoutException">org.openqa.selenium.TimeoutException: </failure> </testcase> <testcase name="login2" classname="com.seewo.training.TestSeewoTraining" time="11.999"> <failure type="java.lang.NullPointerException">java.lang.NullPointerException at com.seewo.training.TestSeewoTraining.login2(TestSeewoTraining.java:25) </failure> <system-out><![CDATA[2016-05-23 20:27:45 dev_log : [INFO] login Failure 2016-05-23 20:27:45 dev_log : [INFO] ./screenShots\login-20160523202745.png 2016-05-23 20:27:45 dev_log : [INFO] login2 Start ]]></system-out> </testcase> </testsuite>
以上的内容我删除掉了部分property的内容。从这里我们就可以通过
<testcase>的标签来识别出是有一条测试用例,并且通过
<failure>是否存在来判断这条测试用例是成功还是失败的。
下来看看我们生成html的代码吧。
/** * 判断字符串中是否包含数字 * @param content 查找的字符串 * @return 是否包含 */ public static boolean hasDigit(String content) { boolean flag = false; Pattern p = Pattern.compile(".*\\d+.*"); Matcher m = p.matcher(content); if (m.matches()) flag = true; return flag; } /** * 获取到最新的目录 * @return 返回目录的名称 */ private static String getLastesFolder() { File path=new File("./target/"); //列出该目录下所有文件和文件夹 File[] files = path.listFiles(); //按照文件最后修改日期倒序排序 Arrays.sort(files, new Comparator<File>() { @Override public int compare(File file1, File file2) { return (int)(file2.lastModified()-file1.lastModified()); } }); //取出第一个(即最新修改的)文件,打印文件名 for (File file : files) { System.out.println(file.getName()); if (hasDigit(file.getName())) { return file.getName(); } } return files[0].getName(); } /** * 读取Suite.xml文件 * @return 对应的html内容 */ public static String readSuitsXml() { XmlParser xmlParser = new XmlParser("./target/"+getLastesFolder()+"/TEST-TestSuite.xml"); List elements = xmlParser.getElementsByTag(xmlParser.getRootElement(), "testcase"); int testCasePass = 0, testCaseFail = 0, testCaseSkip = 0; for (Object element1 : elements) { Element element = (Element) element1; if (xmlParser.getElementByTag(element, "failure") == null) { baseHtml += "<li class=\"list-group-item list-group-item-success\"><strong>" + xmlParser. getElementByAttr(element, "name") + "</strong></li>\n"; testCasePass += 1; }else { baseHtml += "<li class=\"list-group-item list-group-item-danger\"><strong>" + xmlParser. getElementByAttr(element, "name") + "</strong></li>\n"; testCaseFail += 1; } } baseHtml +="</ul>\n" + "</div>\n" + "</body>\n" + "</html>"; baseHtml = baseHtml.replace("SUCCESSCOUNT", String.valueOf(testCasePass)); baseHtml = baseHtml.replace("FAILCOUNT", String.valueOf(testCaseFail)); baseHtml = baseHtml.replace("SKIPCOUNT", String.valueOf(testCaseSkip)); return baseHtml; }
以上中还少了个base_html的定义,因为那部分比较长,主要是一些css的定义,采用bootstrap中的部分css。
生成html后,实际如果写入到一个html中的话,就可以变成下图这样子了。
邮件的发送
既然邮件不能够依赖jenkins,那肯定得自己去实现这部分的内容了。所以我们还是得依赖一些第三方的jar包。我们在pom.xml配置。<dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4.1</version> </dependency>
下来再来看看具体的发送邮件的代码吧
String to[] = { "xxxx.com" }; // 配置发送邮件的环境属性 final Properties props = new Properties(); /* * 可用的属性: mail.store.protocol / mail.transport.protocol / mail.host / * mail.user / mail.from */ // 表示SMTP发送邮件,需要进行身份验证 props.put("mail.smtp.auth", "true"); props.put("mail.smtp.host", "smtp.cvte.com"); // 发件人的账号 props.put("mail.user", "xxx@cvte.com"); // 访问SMTP服务时需要提供的密码 props.put("mail.password", "xxxxx"); // 构建授权信息,用于进行SMTP进行身份验证 Authenticator authenticator = new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { // 用户名、密码 String userName = props.getProperty("mail.user"); String password = props.getProperty("mail.password"); return new PasswordAuthentication(userName, password); } }; // 使用环境属性和授权信息,创建邮件会话 Session mailSession = Session.getInstance(props, authenticator); // 创建邮件消息 MimeMessage message = new MimeMessage(mailSession); // 设置发件人 InternetAddress form = new InternetAddress(props.getProperty("mail.user")); message.setFrom(form); // 设置收件人 String toList = "xxxx"; InternetAddress[] iaToList = new InternetAddress().parse(toList); // 设置多个收件人 message.setRecipients(RecipientType.TO, iaToList); // 设置抄送 // InternetAddress cc = new InternetAddress("wuguohui@cvte.com"); // message.setRecipient(RecipientType.CC, cc); // 设置密送,其他的收件人不能看到密送的邮件地址 // InternetAddress bcc = new InternetAddress("aaaaa@163.com"); // message.setRecipient(RecipientType.CC, bcc); // 设置邮件标题 message.setSubject("Web Auto Test Mail"); message.setContent(GenerateHtml.readSuitsXml(), "text/html;charset=UTF-8"); // 发送邮件 Transport.send(message); System.out.println("成功发送邮件");
这里就是发送的邮件的方法了,可是又来问题了,我们需要在什么时候调用这个发送邮件的方法呢。一开始的想法是在
aftersuite方法后调用。结果发现问题来了,我们在aftersuite的时候,测试报告实际上还没有生成,所以我们根本就拿不到数据,那还有其他办法吗。答案当然是有的啦。
exec-maven-plugin
这个插件就能够帮我们解决问题了。这个插件的作用就是调动某个java文件的main方法。所以我们只要在前面的pom.xml之后再配置。<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.1.1</version> <executions> <execution> <phase>test</phase> <goals> <goal>java</goal> </goals> <configuration> <includePluginDependencies>true</includePluginDependencies> <mainClass>com.seewo.training.utils.SendMail</mainClass> <arguments> <argument>11</argument> <argument>22</argument> </arguments> </configuration> </execution> </executions> </plugin>
指明我们运行的阶段以及运行的java类就可以了。但是这里有两点需要注意
java类必须在目录 main/java下才行。不能够在test目录下。
如果testng的配置中没有增加
<testFailureIgnore>true</testFailureIgnore>这句的话,一旦有测试用例执行失败了发送邮件的java类也不会被执行的。
以上两点是需要注意的地方了。
相关文章推荐
- appium+testng报告更改
- Maven运行TestNG的testcase 两种方式
- Testng测试报告设置那点事~
- ReportNG 支持中文处理技巧
- Intellij IDEA下载和安装并导入reportNG项目
- reportNG定制化之失败截图,包括reportNG打包
- Jenkins发送Email邮件附带reportNG报告
- ReportNG之本地化定制全部以中文显示
- 我的自动化测试历程(Selenium+TestNG+Java+ReportNG+Jenkins)
- Reportng测试报告添加失败用例截图
- UI层自动化测试框架(六):持续集成和测试报告
- ReportNG测试报告的定制修改
- [Android测试] AS+Appium+Java+Win 自动化测试之九:PO模式的实例与ReportNg测试报告
- reportNG定制化修改-支持中文、首页添加饼图、报告显示图片
- 现在有100个标记过的电灯泡。第一个人经过这些灯时,点亮所有的灯,第二个人经过时每隔一盏灯就切换开关一次,第三个人经过时每隔两盏灯切换开关一次。请问,当第100个人经过时,还剩多少盏亮着的灯?
- 【蓝桥杯】连续奇数和
- 《Linux大棚》博客
- bootstrap的ajax提交
- poj 3104 二分枚举答案,最值问题转化为判定性问题
- Android 键盘属性