• testng + reportng 测试结果邮件发送


    https://blog.csdn.net/qq744746842/article/details/51497506

    其实大多数的时候我们的测试报告的发送可能都是结合Jenkins发送的,所以这方面更多的都是依赖于它,可是如果有的时候我们不需要Jenkins的时候,我们应该如何去处理这部分的内容呢

    项目情况
    由于我们使用的是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 FilesJavajdk1.8.0_11jrein"/>
    <property name="java.vm.version" value="25.11-b03"/>
    <property name="java.vm.vendor" value="Oracle Corporation"/>
    <property name="maven.multiModuleProjectDirectory" value="E:eclipseProjectSeewoTraining"/>
    <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 &apos;By.xpath: //*[@id=&apos;username&apos;]&apos;&#10;Build info: version: &apos;2.53.0&apos;, revision: &apos;35ae25b1534ae328c771e0856c93e187490ca824&apos;, time: &apos;2016-03-15 10:43:46&apos;&#10;System info: host: &apos;cvtpc-PC&apos;, ip: &apos;127.0.0.1&apos;, os.name: &apos;Windows 7&apos;, os.arch: &apos;amd64&apos;, os.version: &apos;6.1&apos;, java.version: &apos;1.8.0_11&apos;&#10;Driver info: org.openqa.selenium.chrome.ChromeDriver&#10;Capabilities [{applicationCacheEnabled=false, rotatable=false, mobileEmulationEnabled=false, chrome={chromedriverVersion=2.21.371459 (36d3d07f660ff2bc1bf28a75d1cdabed0983e7c4), userDataDir=C:UserscvtpcAppDataLocalTempscoped_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}]&#10;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] ./screenShotslogin-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> ";
    testCasePass += 1;
    }else {
    baseHtml += "<li class="list-group-item list-group-item-danger"><strong>" + xmlParser.
    getElementByAttr(element, "name") + "</strong></li> ";
    testCaseFail += 1;
    }
    }
    baseHtml +="</ul> " +
    "</div> " +
    "</body> " +
    "</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类也不会被执行的。
    以上两点是需要注意的地方了。
    ---------------------
    作者:saii
    来源:CSDN
    原文:https://blog.csdn.net/qq744746842/article/details/51497506
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    Palindrome Linked List 解答
    Word Break II 解答
    Array vs Linked List
    Reverse Linked List II 解答
    Calculate Number Of Islands And Lakes 解答
    Sqrt(x) 解答
    Find Median from Data Stream 解答
    Majority Element II 解答
    Binary Search Tree DFS Template
    188. Best Time to Buy and Sell Stock IV
  • 原文地址:https://www.cnblogs.com/ceshi2016/p/10005737.html
Copyright © 2020-2023  润新知