1.1什么是自动化测试框架
1.什么是自动化框架
自动化框架是应用与自动化测试的程序框架,它提供了可重用的自动化测试模块,提供最基础的自动化测试功能,或提供自动化测试执行和管理功能的架构模块。它是由一个或多个自动化测试基础模块、自动化管理模块、自动化测试统计模块等组成的工具集合
2.自动化测试框架常见的4种模式
1)数据驱动测试框架
使用数据数组、测试数据文件或者数据库等方式接入自动化测试框架,此框架一般用于在一个测试中使用多组不同的测试数据
2)关键字驱动测试框架
关键字驱动使用被操作的元素对象、操作的方法和操作的数值作为测试过程输入的自动化测试框架,可以兼容更多的自动化测试操作类型,大大提高了自动化测试框架的使用灵活性
3)混合型测试框架
在关键字驱动测试框架中加入了数据驱动功能
4)行为驱动测试框架
支持自然语言作为测试用例描述的自动化测试框架,例如前面章节讲到的Cucumber框架
3.自动化测试框架的作用
(1)能够有效组织和管理测试脚本
(2)进行数据驱动或关键字驱动的测试
(3)将基础的测试代码进行封装,降低测试脚本编写的复杂性和重复性
(4)提高测试脚本维护和修改的效率
(5)自动执行测试脚本,并自动发布测试报告,为持续集成的开发方式提供脚本支持
(6)让不具备编程能力的测试工程师开展自动化测试工作
4.自动化测试框架的核心设计思想
自动化测试框架的核心思想是将常用的脚本代码或者测试逻辑进行抽象和总结,然后将这些代码进行面向对象设计,将需要复用的代码封装到可公用的类方法中
1.2数据驱动框架及实战
数据驱动框架搭建步骤:
(1)新建一个java工程,命名为DataDrivenFrameWork,配置好工程中的WebDriver和TestNG环境环境,并导入Excel操作相关和Log4j相关的JAR文件到工程中
(2)新建4个Package分别命名为:
cn.gloryroad.appModules,主要用于实现复用的业务逻辑封装方法
cn.gloryroad.pageObjects,主要用于实现被测试对象的页面对象
cn.gloryroad.testScripts,主要用于实现具体的测试脚本逻辑
cn.gloryroad.util,主要用于实现测试过程中调用方法例如文件操作、页面元素对象操作
(3)在cn.gloryroad.util的Package中新建ObjectMap类,代码如下
package cn.gloryroad.util; import java.io.FileInputStream; import java.util.Properties; import org.openqa.selenium.By; public class ObjectMap { Properties properties; public ObjectMap(String propFile){ properties = new Properties(); try { FileInputStream in = new FileInputStream(propFile); properties.load(in); in.close(); } catch (Exception e) { System.out.println("读取对象文件出错"); e.printStackTrace(); } } public By getLocator(String ElementNameInpropFile) throws Exception{ //根据变量ElementNameInpropFile从属性文件中读取对应的配置文件 String locator = properties.getProperty(ElementNameInpropFile); //将配置对象的定位类型存到locatorType变量,将表达式的值存入locatorValue变量 String locatorType = locator.split(">")[0]; String locatorValue = locator.split(">")[1]; //默认为ISO-8859-1编码存储,使用getBytes方法可以将字符串编码转换为UTF-8,解决在配置文件读取中文乱码问题 locatorValue = new String(locatorValue.getBytes("ISO-8859-1"),"UTF-8"); //输出locatorType和locatorValue变量的值,验证赋值是否正确 System.out.println("获取的定位类型:"+locatorType+"\t获取的定位表达式"+locatorValue); //根据locatorType的变量值内容判断返回何种定位方式的By if(locatorType.toLowerCase().equals("id")) return By.id(locatorValue); else if(locatorType.toLowerCase().equals("name")) return By.name(locatorValue); else if((locatorType.toLowerCase().equals("classname")) || (locatorType.toLowerCase().equals("class"))) return By.className(locatorValue); else if((locatorType.toLowerCase().equals("tagname")) || (locatorType.toLowerCase().equals("tag"))) return By.tagName(locatorValue); else if((locatorType.toLowerCase().equals("linktext")) || (locatorType.toLowerCase().equals("link"))) return By.linkText(locatorValue); else if(locatorType.toLowerCase().equals("partiallinktext")) return By.partialLinkText(locatorValue); else if((locatorType.toLowerCase().equals("cssselector")) || (locatorType.toLowerCase().equals("css"))) return By.cssSelector(locatorValue); else if(locatorType.toLowerCase().equals("xpath")) return By.xpath(locatorValue); else throw new Exception("输入的咯差投入type未在程序中被定义:"+locatorType); } }
(4)在工程中添加一个存储页面表达式和定位方式的配置文件objectMap.properties内容如下:
163mail.loginPage.username=xpath>//input[@placeholder='\u90AE\u7BB1\u8D26\u53F7\u6216\u624B\u673A\u53F7\u7801'] 163mail.loginPage.password=xpath>//input[@placeholder='\u8F93\u5165\u5BC6\u7801'] 163mail.loginPage.loginbutton=id>dologin
(5)在cn.gloryroad.pageObjects的Package下新建类LoginPage,用于实现163邮箱登录页面的PageObject对象。LoginPage类代码如下:
package cn.gloryroad.pageObjects; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import cn.gloryroad.util.ObjectMap; public class LoginPage { private WebElement element = null; //指定元素定位表达式配置文件的绝对路径 private ObjectMap objectMap = new ObjectMap("E:\\project\\DataDrivenFrameWork\\objectMap.properties"); private WebDriver driver; public LoginPage(WebDriver driver){ this.driver = driver; } //返回登录页面中的用户名输入框页面元素对象 public WebElement userName() throws Exception { element = driver.findElement(objectMap.getLocator("163mail.loginPage.username")); return element; } //返回登录页面中的密码输入框页面元素对象 public WebElement password() throws Exception{ element = driver.findElement(objectMap.getLocator("163mail.loginPage.password")); return element; } //返回登录页面中的登录按钮的页面元素对象 public WebElement loginButton() throws Exception{ element = driver.findElement(objectMap.getLocator("163mail.loginPage.loginbutton")); return element; } }
(6)在cn.gloryroad.testScripts的Package中新建TestMaill163Login测试类,具体测试代码如下:
package cn.gloryroad.testScripts; import org.testng.annotations.Test; import cn.gloryroad.pageObjects.LoginPage; import junit.framework.Assert; import org.testng.annotations.BeforeMethod; import java.util.concurrent.TimeUnit; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.testng.annotations.AfterMethod; public class TestMail163Login { public WebDriver driver; String url = "http://mail.163.com/"; @Test public void testMailLogin()throws Exception { driver.get(url); driver.switchTo().frame(0); LoginPage loginPage = new LoginPage(driver); loginPage.userName().sendKeys("m17805983076"); loginPage.password().sendKeys("*****"); loginPage.loginButton().click(); Thread.sleep(5000); Assert.assertTrue(driver.getPageSource().contains("未读邮件")); } @BeforeMethod public void beforeMethod() { //设定Chrome支持的绝对路径 System.setProperty("webdriver.chrome.driver", "D:\\WebDriver\\chromedriver_win32\\chromedriver.exe"); driver = new ChromeDriver(); driver.manage().window().maximize(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); } @AfterMethod public void afterMethod() { driver.quit(); } }
(7)在cn.gloryroad.appModules中新增Login_Actiob类,具体代码如下
package cn.gloryroad.appModules; import org.openqa.selenium.WebDriver; import cn.gloryroad.pageObjects.LoginPage; public class Login_Action { public static void execute(WebDriver driver,String userName,String passWord)throws Exception{ driver.get("http://mail.163.com"); LoginPage loginPage = new LoginPage(driver); driver.switchTo().frame(0); loginPage.userName().sendKeys(userName); loginPage.password().sendKeys(passWord); loginPage.loginButton().click(); Thread.sleep(5000); } }
(8)修改测试类TestMail163Login的代码,修改后的代码如下
package cn.gloryroad.testScripts; import org.testng.annotations.Test; import cn.gloryroad.appModules.Login_Action; import cn.gloryroad.pageObjects.LoginPage; import junit.framework.Assert; import org.testng.annotations.BeforeMethod; import java.util.concurrent.TimeUnit; import org.apache.log4j.xml.DOMConfigurator; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.testng.annotations.AfterMethod; public class TestMail163Login { public WebDriver driver; String url = "http://mail.163.com/"; @Test public void testMailLogin()throws Exception { Login_Action.execute(driver, "m17805983076", "*****"); Thread.sleep(5000); Assert.assertTrue(driver.getPageSource().contains("未读邮件")); } @BeforeMethod public void beforeMethod() { DOMConfigurator.configure("log4j.xml"); //设定Chrome支持的绝对路径 System.setProperty("webdriver.chrome.driver", "D:\\WebDriver\\chromedriver_win32\\chromedriver.exe"); driver = new ChromeDriver(); driver.manage().window().maximize(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); } @AfterMethod public void afterMethod() { driver.quit(); } }
比较修改前后的代码登录操作步骤被一个函数调用就替代了,实现了业务逻辑的封装,减少了脚本的重复编写
(9)在cn.gloryroad.pageobject的Package中新建HomePage和AddressBookPage类,并在配置文件objectMap.properties中补充新的定位表达式
配置文件objectMap.properties配置文件更新后的内容如下
163mail.loginPage.username=xpath>//input[@placeholder='\u90AE\u7BB1\u8D26\u53F7\u6216\u624B\u673A\u53F7\u7801'] 163mail.loginPage.password=xpath>//input[@placeholder='\u8F93\u5165\u5BC6\u7801'] 163mail.loginPage.loginbutton=id>dologin 163mail.homePage.addressbook=xpath>//li[@title='\u901A\u8BAF\u5F55'] 163mail.addressBook.createContactPerson=xpath>//span[text()='\u65B0\u5EFA\u8054\u7CFB\u4EBA'] 163mail.addressBook.contactPersonName=id>input_N 163mail.addressBook.contactPersonEmail=xpath>//*[@id='iaddress_MAIL_wrap']//input 163mail.addressBook.contactPersonMobile=xpath>//*[@id='iaddress_TEL_wrap']//input 163mail.addressBook.saveButton=xpath>//span[text()='\u786E \u5B9A']
HomePage类代码如下:
package cn.gloryroad.pageObjects; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import cn.gloryroad.util.ObjectMap; public class HomePage { private WebElement element = null; private ObjectMap objectMap = new ObjectMap("E:\\project\\DataDrivenFrameWork\\objectMap.properties"); private WebDriver driver; public HomePage(WebDriver driver){ this.driver = driver; } //获取登录后主页中的“通讯录”链接 public WebElement addressLink() throws Exception{ element = driver.findElement(objectMap.getLocator("163mail.homePage.addressbook")); return element; } //如果要在HomePage页面操作更多元素,可根据需要自定义 }
AddressBookPage类代码如下
package cn.gloryroad.pageObjects; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import cn.gloryroad.util.ObjectMap; public class AddressBookPage { private WebElement element = null; private ObjectMap objectMap = new ObjectMap("E:\\project\\DataDrivenFrameWork\\objectMap.properties"); private WebDriver driver; public AddressBookPage(WebDriver driver){ this.driver = driver; } //获取新建联系人按钮 public WebElement createContactPersonButton() throws Exception{ element = driver.findElement(objectMap.getLocator("163mail.addressBook.createContactPerson")); return element; } //获取新建联系人姓名输入框 public WebElement contactPersonName() throws Exception{ element = driver.findElement(objectMap.getLocator("163mail.addressBook.contactPersonName")); return element; } //获取新建联系人界面中的电子邮件输入框 public WebElement contactPersonEmail() throws Exception{ element = driver.findElement(objectMap.getLocator("163mail.addressBook.contactPersonEmail")); return element; } //获取新建联系人手机号码输入框 public WebElement contactPersonMobile() throws Exception{ element = driver.findElement(objectMap.getLocator("163mail.addressBook.contactPersonMobile")); return element; } //获取新建联系人界面中保存信息的确定按钮 public WebElement saveButton() throws Exception{ element = driver.findElement(objectMap.getLocator("163mail.addressBook.saveButton")); return element; } }
(10)在cn.gloryroad.appModules中增加ADDContactPerson_Action类具体类代码如下
package cn.gloryroad.appModules; import org.openqa.selenium.WebDriver; import cn.gloryroad.pageObjects.LoginPage; public class Login_Action { public static void execute(WebDriver driver,String userName,String passWord)throws Exception{ driver.get("http://mail.163.com"); LoginPage loginPage = new LoginPage(driver); driver.switchTo().frame(0); loginPage.userName().sendKeys(userName); loginPage.password().sendKeys(passWord); loginPage.loginButton().click(); Thread.sleep(5000); } }
(11)在cn.gloryroad.testScripts的Package包中新增测试类TestMail163AddContactPerson,测试类的代码如下
package cn.gloryroad.testScripts; import org.testng.annotations.Test; import cn.gloryroad.appModules.AddContactPerson_Action; import org.testng.annotations.BeforeMethod; import java.util.concurrent.TimeUnit; import org.junit.Assert; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.testng.annotations.AfterMethod; public class TestMail163AddContactPerson { public WebDriver driver; String url = "http://mail.163.com/"; @Test public void testAddContactPerson()throws Exception { AddContactPerson_Action.execute(driver, "m17805983076", "*****", "张三", "zhangsan@163.com", "17807805930"); Thread.sleep(3000); Assert.assertTrue(driver.getPageSource().contains("张三")); Assert.assertTrue(driver.getPageSource().contains("zhangsan@163.com")); Assert.assertTrue(driver.getPageSource().contains("17807805930")); } @BeforeMethod public void beforeMethod() { System.setProperty("webdriver.chrome.driver", "D:\\WebDriver\\chromedriver_win32\\chromedriver.exe"); driver = new ChromeDriver(); driver.manage().window().maximize(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); } @AfterMethod public void afterMethod() { driver.quit(); } }
(12)在cn.gloryroad.util的Package中新建Constant类,具体代码如下
package cn.gloryroad.util; public class Constant { //定义测试网址的常量 public static final String Url = "http://mail.163.com/"; //定义邮箱用户名的常量 public static final String MialUsername = "m17805983076"; //定义邮箱密码的常量 public static final String MailPassword = "******"; //定义新建联系人用户名的常量 public static final String ContactPersonName = "张三"; //定义新建联系人邮箱的常量 public static final String ContactPersonEmail = "zhangsan@163.com"; //定义新建联系人手机号码的常量 public static final String ContactPersonMobile = "17807805930"; }
在cn.gloryroad.testScripts的Package中修改TestMail163AddContactPerson测试类代码,修改后代码如下
package cn.gloryroad.testScripts; import org.testng.annotations.Test; import cn.gloryroad.appModules.AddContactPerson_Action; import cn.gloryroad.util.Constant; import org.testng.annotations.BeforeMethod; import java.util.concurrent.TimeUnit; import org.junit.Assert; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.testng.annotations.AfterMethod; public class TestMail163AddContactPerson { public WebDriver driver; //调用Constant类中的常量 private String url = Constant.Url; @Test public void testAddContactPerson()throws Exception { driver.get(url); //调用Constant类中的常量 AddContactPerson_Action.execute(driver, Constant.MialUsername, Constant.MailPassword, Constant.ContactPersonName, Constant.ContactPersonEmail, Constant.ContactPersonMobile); Thread.sleep(3000); Assert.assertTrue(driver.getPageSource().contains(Constant.ContactPersonName)); Assert.assertTrue(driver.getPageSource().contains(Constant.ContactPersonEmail)); Assert.assertTrue(driver.getPageSource().contains(Constant.ContactPersonMobile)); } @BeforeMethod public void beforeMethod() { System.setProperty("webdriver.chrome.driver", "D:\\WebDriver\\chromedriver_win32\\chromedriver.exe"); driver = new ChromeDriver(); driver.manage().window().maximize(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); } @AfterMethod public void afterMethod() { driver.quit(); } }