• 关于selenium的CI、框架……


    这段时间除了项目测试外,主要在做web自动化的事情,大致总结一下吧,总体的设计模式pageobject+pagefactory+testng的数据驱动,项目用maven来构建,使用jenkins集成,用grid分布式部署,支持并发。下面分别来简单说下注意事项吧。

    一、jenkins

    代码放在git上,除了常规的设置git插件外,需要注意

    1.触发构建

      选择,Build periodically。0 * * * * 表示的就是每个小时的第 0 分钟执行一次构建。参数含义:

    • 第一个参数代表的是分钟 minute,取值 0~59;
    • 第二个参数代表的是小时 hour,取值 0~23;
    • 第三个参数代表的是天 day,取值 1~31;
    • 第四个参数代表的是月 month,取值 1~12;
    • 最后一个参数代表的是星期 week,取值 0~7,0 和 7 都是表示星期天。

    2.构建步骤

      运行pom文件,命令是

    clean install compile test-compile test

      一定要把maven中的main和test一起编译。

    3.测试报告

      目前公司的Jenkins安装的插件是publish testng results,路径默认即可 。**/testng-results.xml,效果图如下:

    4.发送邮件

       邮件触发选择always,content我暂时设计了一个模板,以后再优化,效果如下

    代码如下:

    hi all,<br/><hr/>
    
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>qiaoyeye</title>
    <style type="text/css">
    <!--
    .STYLE1 {
        font-size: 18px;
        font-weight: bold;
        color: #FF0000;
    }
    .STYLE2 {
        font-size: 14px;
        font-weight: bold;
    }
    .STYLE3 {
        color: #00FF00;
        font-weight: bold;
        font-size: 14px;
    }
    .STYLE4 {
        color: #FF0000;
        font-weight: bold;
        font-size: 14px;
    }
    .STYLE5 {
        color: #FFFF00;
        font-weight: bold;
        font-size: 14px;
    }
    .STYLE6 {font-size: 12px}
    -->
    </style>
    </head>
    
    <body>
    <span class="STYLE1">构建结果 - ${BUILD_STATUS}</span>
    <br />
    <br />
    <br />
    <br />
    <br />
    <span class="STYLE2">构建信息</span>
    <hr />
    <br />
    <ul>
    <li>项目名称:${PROJECT_NAME}</li>
    <li>构建编号:${BUILD_NUMBER}</li>
    <li>构建时间:${BUILD_ID}</li>
    <li>触发原因:${CAUSE}</li>
    <li>构建日志:<a href="${BUILD_URL}console">${BUILD_URL}console</a></li>
    <li>构建URL:<a href="${BUILD_URL}">${BUILD_URL}</a></li>
    <li>项目URL:<a href="${PROJECT_URL}">${PROJECT_URL}</li>
    <li>工作目录:<a href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li>
    </ul>
    <br />
    <br />
    <span class="STYLE2">测试概览</span>
    <hr />
    <br />
    <table width="700" height="64" border="1">
      <tr>
        <td bgcolor="#CCCCCC"><div align="center" class="STYLE2">total</div></td>
        <td bgcolor="#CCCCCC"><div align="center" class="STYLE3">passed</div></td>
        <td bgcolor="#CCCCCC"><div align="center" class="STYLE4">failed</div></td>
        <td bgcolor="#CCCCCC"><div align="center" class="STYLE5">skipped</div></td>
      </tr>
      <tr>
        <td><div align="center"><span class="STYLE6"> ${TEST_COUNTS, var="total"}</span></div></td>
        <td><div align="center"><span class="STYLE6"> ${TEST_COUNTS, var="pass"}</span></div></td>
        <td><div align="center"><span class="STYLE6"> ${TEST_COUNTS, var="fail"}</span></div></td>
        <td><div align="center"><span class="STYLE6"> ${TEST_COUNTS, var="skip"}</span></div></td>
      </tr>
    </table>
    <br />
    <br />
    <span class="STYLE2">failure log:</span>
    <hr />
    $FAILED_TESTS
    <br />
    $PASSED_TESTS
    <br />
    $SKIPPED_TESTS
    <br />
    </body>
    </html>
    <br/><hr/>
    (本邮件是程序自动下发的,请勿回复!)<br/><hr/>

     5.可以把失败的截图作为附件添加

    projectjobname/imgfilename/*.png

    **/ExceptionScreenshotImg/**/*.png

    二、maven

    主要是pom文件,需要在pom中添加对testng的支持

    <build>
      <pluginManagement>
      <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.19.1</version>
            <configuration>
              <suiteXmlFiles>
                <!-- <suiteXmlFile> -->
                <file>src/test/java/OmsWebAuto.xml</file>
               <!-- </suiteXmlFile> -->
              </suiteXmlFiles>
            </configuration>
    </plugin>

     pom对reportNG的支持

    <!-- reportng -->
        
        <dependency>
            <groupId>org.uncommons</groupId>
            <artifactId>reportng</artifactId>
            <version>1.1.2</version>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.testng</groupId>
                    <artifactId>testng</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
              <groupId>com.google.inject</groupId>
              <artifactId>guice</artifactId>
              <version>3.0</version>
            </dependency>
            <dependency>
                <groupId>velocity</groupId>
                <artifactId>velocity</artifactId>
                <version>1.4</version>
                <scope>test</scope>
            </dependency>
    <!-- 加入reportNG和testng的插件 -->
    
    <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.5</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>      
                <!-- <suiteXmlFile> -->
                <file>src/test/java/International.xml</file>
               <!-- </suiteXmlFile> -->
              </suiteXmlFiles>
              
            </configuration>
            
          </plugin>

    三、框架

    1.合理利用selenium的监听事件

    可以把一些log或者经常调用的方法等放在监听事件类里,只需要自己新建一个类实现WebDriverEventListener即可,好处是在后面的代码中不需要在写一堆方法或频繁调用了,效果真的不错。注册监听的方法:

    private static EventFiringWebDriver registerEvent(WebDriver driver) {
            EventFiringWebDriver event = new EventFiringWebDriver(driver);
            BaseEventListener eventlis = new BaseEventListener();
            event.register(eventlis);
            return event;
        } 

    2. 利用testng的监听事件

    如失败自动截图,参考我的文章:

    selenium遇到异常自动截图

    失败自动重跑,抽时间再整理成文章:

    等……

    3.所有用例只启动浏览器、登录、关闭浏览器一次

    要想做到这点,首先要明白testng的生命周期,可以参考我的这边文章http://www.cnblogs.com/qiaoyeye/p/5317566.html

    然后核心思想是保证所有的测试类在整个生命周期内用的是同一个webdriver对象,一定要理解,要想做到这一点,就必须单独建立一个类,包含初始化webdriver的方法和webdriver的全局变量,放在合适的testng注解内,其他所有的测试类,都调用该类的webdriver。举例如下:

    •  webdriver初始化类:
    /**
     * 在整个测试中,只启动浏览器、登录至主页、关闭浏览器一次。所有测试类的driver=TestSuite.driver,以保证共用的是一个driver。
     * @author  QiaoJiafei
     * @version 创建时间:2016年5月13日 下午6:48:41
     * 类说明
     */
    public class TestSuite{
        public static WebDriver driver;
        
        @BeforeSuite
        public void befSuite() {
            driver = DriverFactory.setUpDriver();
            visitorURL();
            Login.login(driver);
            //直接进入订单系统页面
            HomePage homepage = new HomePage(driver);
            homepage.jumpProduct();
        }
        private void visitorURL() {
            String url = OptionFile.readProperties("./src/test/resources/logininfo.properties", "URL");
            driver.get(url);
        }
    
        @AfterSuite
        public void aftSuite() {
            DriverFactory.tearDownDriver(driver);
        }
    }
    • 测试类,注意这里把testsuite的driver赋值给了driver,保证了整个生命周期用的都是同一个driver
    public class TestOrderSearch extends BaseTestClass{
        @Test
        public void testOrderSerach() {
            driver = TestSuite.driver;
            OrderHomePage odp = new OrderHomePage(driver);
            OrderSearchPage osp = odp.jumpOrderSearch();
            osp.searchOrder();
            osp.clickOrderDetail();
            
        }
    }
    • Driverfactory就是一个初始化和销毁driver的工厂类。

    4.pafactory遇到iframe怎么办

    我的解决办法是三种,在同一个类内解决,不同类解决,内部类解决。

    • 同一个类

      在同一个类中的话,在使用iframe中的元素时一定要先切换ifame,使用完元素后,要记得切回主体。这种办法适合iframe中要使用的元素比较少时使用。

    • 内部类

      在内部类的话,等于把处理iframe的元素抽象到了一个类中,切换iframe和切回主体都在内部类中,这样其他类只需要调用内部类即可,不需要在关心iframe的处理,适合iframe中有适量的元素处理

      

        public class Inner  extends BasePage{
            
            public Inner(WebDriver driver) {
                super(driver);
                this.toFrame("ueditor_0");
            }
            //
            @FindBy(xpath="/html/body")
            WebElement rich_body;
            
            public void setContent() {
                this.setRichTextBox(rich_body, "web ui auto test");
                this.toDefaultContent();
            }
        }
    • 不同的类

      和内部类类似,使用要在iframe处理的元素比较多,就可以单独拉出啦作为一个类处理。

    5.活用反射

    java的反射真的太好了,目前主要用在:

    • 在数据驱动动态获取必要参数,因为testng的数据驱动不支持主动调用传参的。
    • 自动截图中,自动以运行的类名来命名文件夹,然后以方法名+时间戳来命名图片。
    • pagefactory初始化之前,从property文件中获取当前正在运行的类的标题,key是类名,value是标题,这样只需要配置好property文件就行,省了不少麻烦。

    四、grid

    这个没什么好说的,一台电脑启动hub,然后在不同的机器上启动node,注册到该hub上,grid会根据框架对浏览器的配置来分配相应的node启动浏览器测试,selenium官网上有很多这方面的介绍,这里只介绍下我常用的命令

    •  hub:

      

    java -jar selenium-server-standalone-2.53.0.jar -role hub
    • node1:

      

    java -Dwebdriver.chrome.driver=C:selenium
    ode_chrome32_windowsdriverchromedriver.exe -jar selenium-server-standalone-2.53.0.jar -role node -hub http://192.168.15.54:4444/grid/register -maxSession 20 -browser "browserName=chrome,platform=WINDOWS,maxInstances=20" -port 5556
    • node2
    • …………

    上面的命令更换浏览器名称、端口、路径即可


    目前只是初步成型,后面还有很多工作要做。

  • 相关阅读:
    emacs jedi
    opencv 基本demo
    emacs列编辑
    observable operator example
    angular keydown 例子
    回调和匿名函数
    gin cors
    angular rxjs
    python dbus note
    视频截图
  • 原文地址:https://www.cnblogs.com/qiaoyeye/p/5510353.html
Copyright © 2020-2023  润新知