zoukankan      html  css  js  c++  java
  • 2018-04-13web自动化学习心得(1)

    selenium版本说明-->firefox,ie,chrome驱动文件-->集成testNG-->参数化测试-->分组测试-->元素定位(非xpath,xpath)


    -- selenium版本说明
    selenium2.53.0+firefox 46
    selenium3.5.1+firefox 56
    geckodriver.exe高版本火狐需要下载驱动
    放在src/test/resources/geckodriver.exe路径下

    -- 依赖包
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>3.5.1</version>
    </dependency>

    -- 例子
    public class FirefoxDemo {
    public static void main(String[] args) throws InterruptedException {
        //驱动文件
        System.setProperty("webdriver.gecko.driver", "src/test/resources/geckodriver.exe");
        WebDriver webDriver=new FirefoxDriver();
        webDriver.get("http://www.baidu.com");
        webDriver.findElement(By.id("kw")).sendKeys("哈哈哈");
        webDriver.findElement(By.id("su")).click();
        Thread.sleep(2000);
        webDriver.quit();
    }
    }
    -- 51
    --ie下的第一个坑
    使用ie浏览器完成自动化测试时,代码报如下错误:The path to the driver executable
    没有驱动导致,下载驱动到指定位置:src/test/resources/IEDriverServer.exe
    下载地址:http://www.seleniumhq.org/download
    建议下载3.7.0版本

    -- ie下第二个坑
    需要忽略浏览器保护模式:pratected modesettings are not the same for all zones
    解决办法,忽略此设置,加一段下面代码:
    InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS

    -- ie下第三个坑
    浏览器缩放级别设置不对导致
    解决方法,忽略缩放,加一段下面代码:InternetExplorerDriver.IGNORE_ZOOM_SETTING

    -- ie下第四个坑
    window对象丢失,unable to find element with css selector==#kw
    解决方法,直接指定一个初始化页面,加一段下面代码:InternetExplorerDriver.INITIAL_BROWSER_URL

    public class IEDemo {
        public static void main(String[] args) throws InterruptedException {
            System.setProperty("webdriver.ie.driver","src/test/resources/IEDriverServer.exe");
            //创建驱动对象
            DesiredCapabilities capabilities=new DesiredCapabilities();
            capabilities.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true);
            capabilities.setCapability(InternetExplorerDriver.IGNORE_ZOOM_SETTING, true);
            capabilities.setCapability(InternetExplorerDriver.INITIAL_BROWSER_URL, "http://www.baidu.com");
            WebDriver driver=new InternetExplorerDriver();
            //打开ie浏览器,输入百度
            driver.get("http://www.baidu.com");
            //往搜索框输入查询内容
            driver.findElement(By.id("kw")).sendKeys("哈哈哈");
            driver.findElement(By.id("su")).click();
            //等待2s
            Thread.sleep(2000);
            //关闭浏览器
            driver.quit();
        }
    }

    -- chrome
    选中文件名 ctrl+shift+r,可以找到资源文件

    -- chrome错误分析
    Chrome浏览器版本过高,解决办法:降级chrome
    http://www.chromedownloads.net/chrome64win/
    谷歌各版本下载地址

    没有驱动,解决办法:下载驱动
    http://www.seleniumhq.org/download/
    浏览器各版本驱动下载地址
    ps:需要FQ


    -- 集成testng
    依赖包
    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>6.8.8</version>
        <scope>test</scope>
    </dependency>
    集成方法
    1,featuresorg.testng.eclipse_6.9.8.201510130443
    文件夹放到eclipse的features目录下(4k)
    2,pluginsorg.testng.eclipse_6.9.8.201510130443
    文件夹放到eclipse的plugins目录下(2.8m)
    3,重启eclipse
    4,验证是否集成成功:new--》testng class

    -- testng.xml
    在项目的根目录底下创建testNG.xml
    一个suite(套件)由一个或多个测试构成
    一个test(测试)是由一个或多个类组成
    class(类)是由一个或多个方法组成
    parameter:定义参数
    执行方法:右键testng.xml-->run as TestNG Suite

    -- 常用注解
    @BeforeSuite、@AfterSuite在某个测试套件suite开始之前、或者之后运行,只运行一次
    @BeforeTest、@AfterTest在某一个测试test开始之前、之后运行,只运行一次(指的是testng.xml文件的test,不是测试类)
    @BeforeClass、@AfterClass在某个测试类class开始之前、之后运行,只运行一次
    @BeforeMethod、@AfterMethod在某个测试方法method开始之前、之后运行,每个test都运行一次

    1注解
    import org.testng.annotations.AfterClass;
    import org.testng.annotations.AfterMethod;
    import org.testng.annotations.AfterSuite;
    import org.testng.annotations.AfterTest;
    import org.testng.annotations.BeforeClass;
    import org.testng.annotations.BeforeMethod;
    import org.testng.annotations.BeforeSuite;
    import org.testng.annotations.BeforeTest;
    import org.testng.annotations.Test;

    public class TestNGAnnotaioons {
        @BeforeSuite
        public void beforeSuite(){
            System.out.println("testngannotaioons.beforesuite()");
        }
        @BeforeTest
        public void beforetest(){
            System.out.println("testngannotaioons.beforetest()");
            }
        @BeforeClass
        public void beforeClass(){
            System.out.println("testngannotaioons.beforeclass()");
        }
        @BeforeMethod
        public void beforemethod(){
            System.out.println("testngannotaioons.beforemethod()");
        }
        @Test
        public void test(){
            System.out.println("testngannotaioons.test()");
        }
        @AfterClass
        public void afterClass(){
            System.out.println("testngannotaioons.afterclass()");
        }    
        @AfterTest
        public void aftertest(){
            System.out.println("testngannotaioons.aftertest()");
            }
        @AfterMethod
        public void aftermethod(){
            System.out.println("testngannotaioons.aftermethod()");
        }
        @Test
        public void test1(){
            System.out.println("testngannotaioons.test1()");
        }
        @AfterSuite
        public void afterSuite(){
            System.out.println("testngannotaioons.aftersuite()");
        }

    }
    2xml执行
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
    <suite name="后台管理系统">
       <test name="注解测试">
           <classes>
           <class name="com.mingmenban.testng.TestNGAnnotaioons"></class>
           </classes>
       </test>
    </suite>
    3运行结果
    testngannotaioons.beforesuite()
    testngannotaioons.beforetest()
    testngannotaioons.beforeclass()
    testngannotaioons.beforemethod()
    testngannotaioons.test()
    testngannotaioons.aftermethod()
    testngannotaioons.beforemethod()
    testngannotaioons.test1()
    testngannotaioons.aftermethod()
    testngannotaioons.afterclass()
    testngannotaioons.aftertest()
    testngannotaioons.aftersuite()
     -- 参数化测试(数据驱动测试)
     TestNG可以通过两种方式向测试方法传递参数
    1 利用testng.xml定义parameter
    2利用DataProviders
     解释
     在testng.xml定义parameter参数,在创建test的时候传入参数
    例子
    1传入形参"browserType","driverPath","seleniumVersion"
    public class ParameterDemo {
        @Test(parameters={"browserType","driverPath","seleniumVersion"})
        public void parameter(String browserType,String driverPath, String seleniumVersion) throws Exception{
            WebDriver driver=null;
            if("firefox".equalsIgnoreCase(browserType)){
                if("3.X".equals(seleniumVersion)){
                    System.setProperty("webdriver.gecko.driver", driverPath);
                }
                driver=new FirefoxDriver();
            }else if("IE".equalsIgnoreCase(browserType)&&"3.X".equals(seleniumVersion)){
                System.setProperty("webdriver.ie.driver",driverPath);
                DesiredCapabilities capabilities=new DesiredCapabilities();
                capabilities.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true);
                capabilities.setCapability(InternetExplorerDriver.IGNORE_ZOOM_SETTING, true);
                capabilities.setCapability(InternetExplorerDriver.INITIAL_BROWSER_URL, "http://www.baidu.com");
                driver=new InternetExplorerDriver();
            }else if("chrome".equalsIgnoreCase(browserType)&&"3.X".equals(seleniumVersion)){
                System.setProperty("webdriver.chrome.driver",driverPath);
                driver=new ChromeDriver();
            }
            driver.get("http://www.baidu.com");
            Thread.sleep(2000);
            driver.quit();
        }
    }
    2.运行testng.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
    <suite name="后台管理系统">
       <test name="自动选择浏览器测试">
           <classes>
           <class name="com.mingmenban.testng.ParameterDemo"></class>
           </classes>
       </test>
       <parameter name="browserType" value="firefox"></parameter>
       <parameter name="driverPath" value="src/test/resources/geckodriver.exe"></parameter>
       <parameter name="seleniumVersion" value="3.X"></parameter>
    </suite>

    -- 优化把浏览器驱动定义在父类,两个子类测试类分别继承父类,运行testng.xml配置文件执行自动化测试
    public class Base {
        public static WebDriver driver;
        @BeforeSuite
        @Parameters({"browserType","driverPath","seleniumVersion"})
        public void setup(String browserType,String driverPath, String seleniumVersion){
            if("firefox".equalsIgnoreCase(browserType)){
                if("3.X".equals(seleniumVersion)){
                    System.setProperty("webdriver.gecko.driver", driverPath);
                }
                driver=new FirefoxDriver();
            }else if("IE".equalsIgnoreCase(browserType)&&"3.X".equals(seleniumVersion)){
                System.setProperty("webdriver.ie.driver",driverPath);
                DesiredCapabilities capabilities=new DesiredCapabilities();
                capabilities.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true);
                capabilities.setCapability(InternetExplorerDriver.IGNORE_ZOOM_SETTING, true);
                capabilities.setCapability(InternetExplorerDriver.INITIAL_BROWSER_URL, "http://www.baidu.com");
                driver=new InternetExplorerDriver();
            }else if("chrome".equalsIgnoreCase(browserType)&&"3.X".equals(seleniumVersion)){
                System.setProperty("webdriver.chrome.driver",driverPath);
                driver=new ChromeDriver();
            }
        }
        
    }
    public class ParameterDemo extends Base{    
        @Test
        public void parameter(){
            driver.get("http://www.baidu.com");
            System.out.println("ParameterDemo.test1()");
        }
        @Test
        public void parameter2(){
        driver.get("http://www.baidu.com");
            System.out.println("ParameterDemo.test2()");
        }
    }
    public class ParameterDemo2 extends Base {
        
        @Test
        public void test() throws Exception{
            driver.get("http://www.baidu.com");
            System.out.println("ParameterDemo2.test1()");
        }
        @Test
        public void test2() throws InterruptedException{
            driver.get("http://www.baidu.com");
            System.out.println("ParameterDemo2.test2()");
        }
    }
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
    <suite name="后台管理系统">
       <test name="自动选择浏览器测试">
           <classes>
           <class name="com.mingmenban.testng.ParameterDemo"></class>
           <class name="com.mingmenban.testng.ParameterDemo2"></class>
           </classes>
       </test>
       <parameter name="browserType" value="firefox"></parameter>
       <parameter name="driverPath" value="src/test/resources/geckodriver.exe"></parameter>
       <parameter name="seleniumVersion" value="3.X"></parameter>
    </suite>
    备注:
    parameter的局限性:通过parameters注入的参数必须定义在testng.xml中。比如
    @Parameters({"browserType","driverPath","seleniumVersion"})
    <parameter name="browserType" value="firefox"></parameter>
    <parameter name="driverPath" value="src/test/resources/geckodriver.exe"></parameter>
    <parameter name="seleniumVersion" value="3.X"></parameter>
    --  TestNG可以通过利用DataProviders向测试方法传递参数
    public class RegisterTest extends Base{
        @Test(dataProvider="registerDatas")
        public void test1(String nn,String pd,String expected){
            //获取测试页面
            driver.get("http://119.23.241.154:8380/lmcanon/mng/login.html");
            //定位到用户名输入框
            driver.findElement(By.id("nn")).sendKeys(nn);
            //定位到密码输入框
            driver.findElement(By.id("pd")).sendKeys(pd);
            //定位到重复密码输入框
            //点击登录按钮
            driver.findElement(By.id("login")).click();
            //断言来判断实际错误提示信息是否与实际期望值一致
            String actual=driver.findElement(By.xpath("/html/body/div[2]/div[4]/div/label/p")).getText();
            boolean flag=expected.equals(actual);
            Assert.assertTrue(flag);
        }
        @DataProvider(name="registerDatas")
        public Object[][]registerDatas(){
            Object[][] datas = {
                    { "", "", "用户名不能为空" },
                    { "aa", "",  "非法的手机号" },
                    { "18813989449", "",  "密码不能为空" },
                    { "18813989449", "12312", "密码长度至少6位" }
                    };
            return datas;
        }
    }
    -- 依赖测试:
    @dependsOnMethods:测试方法依赖于某方法,例如
    先执行test2在执行test1
    public class TestNGDemo1 {
        @Test(dependsOnMethods={"test2"})
    public void test1(){
        System.out.println("TestNGDemo1.test1()");
    }
        @Test
    public void test2(){
        System.out.println("TestNGDemo1.test2()");
    }
    }

    -- 忽略测试
    当在测试过程中,因为某方便的原因,比如测试方法没有写完
    或者有问题,我们暂时希望它不得到执行,我们就可以添加忽略标签跳过此方法的运行
    @Test(enabled=false),忽略test2不执行
    public class TestNGDemo1 {
        @Test
    public void test1(){
        System.out.println("TestNGDemo1.test1()");
    }
        @Test(enabled=false)
    public void test2(){
        System.out.println("TestNGDemo1.test2()");
    }
    }

    -- 超时测试
    "超时"表示如果单元测试花费的时间超过指定的毫秒数,那么tsetNG将会中止它
    并将其标记为失败。这样在某些业务场景下,我们认为一个请求时间过长我们就可以
    直接宣判它因为超时而失败
    @Test(timeOut=2000),超时后返回错误,timeOut单位为毫秒
    public class TestNGDemo1 {
        @Test
    public void test1(){
        System.out.println("TestNGDemo1.test1()");
    }
        @Test(timeOut=2000)
    public void test2() throws InterruptedException{
            Thread.sleep(3000);
        System.out.println("TestNGDemo1.test2()");
    }
    }
    -- testNG执行Junit测试
    testng提供了一种配置方式使我们不需要去重构已经写好的junit单元测试类在testng.xml中,
    添加一个test,将junit为true,<test name="单元测试" junit="true">,例如
    </test>
        <test name="单元测试" junit="true">
           <classes>
               <class name="com.mingmenban.testng.JunitDemo"></class>
           </classes>
       </test>
       
    -- 工厂:@Factory
    使用户可以自己去创建测试类的对象,被@factory标注的方法必须返回一个object的数组

    -- dataprovider数据提供者or工厂
    数据提供者还是工厂
    数据提供者是向测试方法传递参数,工厂是向构造方法传递参数

    如果不能确定使用哪种方法,那么就看看测试方法所使用的参数
    是否有几个测试方法需要接收到同样的参数?如果是这样,最好是将这样参数保存在一个字段中
    然后在这几个方法中复用这个字段,就意味着最好选择工厂。反之,如果所有的测试方法都需要
    传入不同的参数,那么数据提供者肯是最好的选择
    -- testng继承maven的surefire插件,测试报告查看
    run as -->maven test
    添加build
    <build>  
            <plugins>  
                <plugin>  
                    <groupId>org.apache.maven.plugins</groupId>  
                    <artifactId>maven-surefire-plugin</artifactId>  
                    <version>2.7.1</version>  
                    <configuration>
                        <testFailureIgnore>true</testFailureIgnore>
                        <argLine>-Dfile.encoding=UTF-8</argLine>
                        <suiteXmlFiles>  
                            <suiteXmlFile>testng.xml</suiteXmlFile>  
                        </suiteXmlFiles>  
                    </configuration>  
                </plugin>  
            </plugins>  
    </build>
    testng报告在项目文件夹-->test-output-->index.html
    maven test报告在项目文件夹-->targer-->surefire-reports-->index.html
    当浏览器打开慢时,可以打开报告文件删除用谷歌打开的这段代码,保存后在打开文件
        <script type="text/javascript" src="https://www.google.com/jsapi"></script>

    -- 分组测试
    只想执行个别或者某一部分的测试用例
    1,测试用例方法指定groups
    2,在testng.xml的test中指定相应测试类
    3,在test的groups里面指定run下要执行的分组
    4,当测试用例越来越多,有些分组不想执行,设置方式也一样,test的groups里
    指定run下不需要执行的分组exclude
    5,exclude优先,如果方法既属于G1有属于G2,exclude排除后,那这个方法不会被执行
    @Test(dependsOnGroups={"g2"},groups={"g1"})依赖组的方法也会被执行
    @Test(groups={"g2"})
    @BeforeGroups(groups={"g1"})在执行分组g1前,先执行g2
    例如
    public class GroupDemo {
        @Test(groups={"g1","g2"})
        public void test1(){
            System.out.println("GroupDemo.test1()");
        }
        @Test(groups={"g1"})
        public void test2(){
            System.out.println("GroupDemo.test2()");
        }
        @Test(groups={"g1"})
        public void test3(){
            System.out.println("GroupDemo.test3()");
        }

    }
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
    <suite name="后台管理系统">
       <test name="分组测试">
        <groups>
            <run>
                <include name="g1"></include>
                <exclude name="g2"></exclude>
            </run>
        </groups>
           <classes>
            <class name="com.mingmenban.testng.GroupDemo"></class>
           </classes>
       </test>
       <parameter name="browserType" value="firefox"></parameter>
       <parameter name="driverPath" value="src/test/resources/geckodriver.exe"></parameter>
       <parameter name="seleniumVersion" value="3.X"></parameter>
    </suite>

    -- 元素定位非xpath方式
    By.id:根据id来获取元素,返回单个元素,因为id的值一般是唯一的
    By.name:根据name属性来获取元素,可能返回元素集合
    By.tagName:根据tagName元素标签名来获取元素,可能返回元素集合
    By.className:根据元素样式className来获取元素,可能返回元素集合
    By.cssSelector:根据cssSelector样式选择器来获取元素,可能返回元素集合
    By.linkText:根据超链接的文本内容获取元素
    By.partiallinkText:根据超链接的部分文本内容获取元素


    例子
    1By.tagName
    public class LocateDemo1 extends Base {
        @Test
        public void test() throws InterruptedException{
            driver.get("file:///D:/zuoye/new%201.html");
            List<WebElement>inputs=driver.findElements(By.tagName("input"));
            inputs.get(0).sendKeys("aa");
        }
    }
    2By.linkText
    public class LocateDemo1 extends Base {
        @Test
        public void test() throws InterruptedException{
            driver.get("file:///D:/zuoye/new%201.html");
            List<WebElement>inputs=driver.findElements(By.linkText("测试获取标签中间的值"));
            System.out.println(inputs.get(0).getAttribute("href"));
        }
    }
    3By.cssSelector
    id#
    样式.
    标签名
    1,根据元素标签名:By.cssSelector("input")等同于By.tagName("input")
    2,根据id选择器:By.id("#username")等同于By.id(username)
    3,根据样式选择器:By.cssSelector(".test")等同于By.class(test)
    4,根据元素属性:By.cssSelector("input[type=radio])
    格式为:By.cssSelector([元素属性名=元素属性值])
    使用场景:当要拿的元素没有id,属性,样式等时,就可以拿元素属性值去获取

    -- 什么是xpath
    xpath其实就是一个path,一个描述页面元素位置信息的路径

    -- xpath定位方法
    绝对定位
    相对定位
    -- 绝对路径定位
    登录界面用户名
    /html/body/div[2]/div/form/div/div/input
    绝对定位:绝对路径以单/号表示,而且是让解析引擎从文档的根节点开始解析,也就是html这个节点下开始解析
    路径解释:html-body-第二个div-div...
    缺点:页面一旦发生变化(比如重新设计,路径少了两节),该路径也随之失效,必须重新写
    -- 相对路径定位
    //*[@id="nn"]
    相对定位:相对路径以//表示,则表示让xpath引擎从文档的任意符合的元素节点开始进行解析
    路径解释:
    //;从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置
    *:匹配任意元素节点
    @:选取属性
    相对定位优点:灵活,方便,灵活性底

    例如
    public class XpathDemo extends Base {
        @Test
        public void xpath(){
            driver.get("http://119.23.241.154:8380/lmcanon/mng/login.html");
    //        driver.findElement(By.xpath("/html/body/div[2]/div/form/div/div/input")).sendKeys("aa");
            driver.findElement(By.xpath("//*[@id='nn']")).sendKeys("aa");
        }
    }

    --
    /html/body/form/div[2]/input
    //*[@id='pwd']

    -- xpath相对路径定位方法
    1,通过元素名来定位(//input获取页面的所有input元素)
    2,通过元素名+索引来定位(//form/div/div/input)
    3,使用元素名+属性(//*[@id='pwd'])
    4,使用元素名+包含部分属性值(//*[contains(@id,'log')])
    5,使用元素名+元素的文本内容(//*[text()='文本内容')])
    6,使用元素名+包含元素的部分文本内容(//*[contians(text(),'部分文本内容')])
    例子
    /html/body/div[2]/div/form/div/div/input(绝对路径)
    //form/div/div/input(相对路径)
    //*[@id='nn']")

    -- 获取alert元素
    @Test
        public void test() throws InterruptedException{
            driver.get("file:///D:/zuoye/new%201.html");
            WebElement element=driver.findElements(By.xpath("//input[@id='login']")).get(0);
            element.click();
            String actual=driver.switchTo().alert().getText();
            System.out.println("警告信息:"+actual);
            String expected="请填写用户名密码";
            Assert.assertEquals(actual,expected);
        }
        
    -- 获取iframe元素
    @Test
        public void test() throws InterruptedException{
            driver.get("file:///D:/zuoye/new%201.html");
            driver.switchTo().frame("bframe");//内联框架
            driver.findElement(By.xpath("//*[@id='kw']")).sendKeys("哈哈哈");
            driver.switchTo().defaultContent();//从iframe窗口切换回来
            driver.findElement(By.id("username")).sendKeys("aa");
            
        }

  • 相关阅读:
    core dump相关
    编译与链接的问题
    shell和awk配合使用
    cybergarage-upnp
    miniupnpc
    openssl
    在 linux 下使用 CMake 构建应用程序
    Ubuntu下的多线程下载工具:MultiGet;并与 Firefox 建立关联 uget
    嵌入式web服务器-thttpd
    Android_Layout_xml布局
  • 原文地址:https://www.cnblogs.com/AIME/p/8819820.html
Copyright © 2011-2022 走看看