2018-04-13web自动化学习心得
Posted AIME123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2018-04-13web自动化学习心得相关的知识,希望对你有一定的参考价值。
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,features\org.testng.eclipse_6.9.8.201510130443
文件夹放到eclipse的features目录下(4k)
2,plugins\org.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");
}
以上是关于2018-04-13web自动化学习心得的主要内容,如果未能解决你的问题,请参考以下文章