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");
        
    }

原文地址:https://www.cnblogs.com/AIME/p/8819820.html