博客很久没更新了,最近在研究python PMO, 趁机给java自动化相关的知识点做个总结。
先说Junit,Testng. 这两个都是用来和java配合做自动化单元测试的框架, Testgn介于Junit3和Junit4之间。但是总的来说Testng是优于Junit. 主要表现在以下几个方面:
1.Testng支持更多的标签:
2.在套件测试方面,Testng引入了组的概念,执行套件测试会更灵活。
3.Testng利用dependOnMethods实现依赖测试,Junit目前还不支持。
再介绍下DDT,数据驱动测试,这个思路在自动化测试也是被广泛运用。下面demo是用Testng结合DDT的例子:
import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.util.concurrent.TimeUnit; public class TestNGDDT { private WebDriver driver; private StringBuilder verificationErrors =new StringBuilder(); @DataProvider(name="testData") public Object[][] testData(){ return new Object[][] { new Object[] {"Test","BDD","BDD"}, new Object[] {"Test","DDT","DDT"}, new Object[] {"Test","UTDD","UTDD"} }; } @BeforeMethod public void beforeMethod() { //若无法打开FireFox浏览器,可设定Firefox浏览器的安装路径 System.setProperty("webdriver.gecko.driver", "src/main/resources/Driver/geckodriver.exe"); //打开Firefox浏览器 driver=new FirefoxDriver(); //设定等待时间为5秒 driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS); } @Test(dataProvider="testData") public void testSearch(String searchdata1,String searchdata2,String searchResult) { //打开baidu首页 driver.get("http://www.baidu.com/"); //输入搜索条件 driver.findElement(By.id("kw")).sendKeys(searchdata1+" "+searchdata2); //单击搜索按钮 driver.findElement(By.id("su")).click(); //单击搜索按钮后,等待3秒显示搜索结果 try{ Thread.sleep(3000); }catch(InterruptedException e){ e.printStackTrace(); } //判断搜索的结果是否包含期望的关键字 Assert.assertTrue(driver.getPageSource().contains(searchResult)); } @AfterMethod public void closeMethod() { driver.quit(); } }
由于近来Agile项目的流行,使得越来越重视客户需求,于是一种近似于自然语言的自动化测试模式应运而生,BDD.行为驱动测试。将需求直接转化成测试用例(feature文件),然后针对用例实现测试步骤,具体demo如下:
A:search.feature
Feature: baidu Search Scenario: search selenium in baidu Given go to baidu home When I find baidu logo And I type the search text "selenium" And click the baiduyixia Then verify query result
Feature文件对应生成的java测试文件。
package steps; import cucumber.api.PendingException; import cucumber.api.java.en.And; import cucumber.api.java.en.Given; import cucumber.api.java.en.Then; import cucumber.api.java.en.When; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.testng.Assert; import java.util.concurrent.TimeUnit; public class searchStepdefs { private static WebDriver driver; @And("^I type the search text \"([^\"]*)\"$") public void iTypeTheSearchText(String arg0) throws Throwable { // Write code here that turns the phrase above into concrete actions //throw new PendingException(); //输入搜索条件 driver.findElement(By.id("kw")).sendKeys("selenium"); } @Given("^go to baidu home$") public void goToBaiduHome() throws Throwable { //若无法打开Chrome浏览器,可设定Chrome浏览器的安装路径 System.setProperty("webdriver.chrome.driver", "DDTest/src/main/resources/Driver/chromedriver.exe"); //打开Chrome浏览器 driver=new ChromeDriver(); //设定等待时间为5秒 driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS); driver.get("http://www.baidu.com/"); } @When("^I find baidu logo$") public void iFindBaiduLogo() throws Throwable { // Write code here that turns the phrase above into concrete actions // throw new PendingException(); } @And("^click the baiduyixia$") public void clickTheBaiduyixia() throws Throwable { //单击搜索按钮 driver.findElement(By.id("su")).click(); //单击搜索按钮后,等待3秒显示搜索结果 try{ Thread.sleep(3000); }catch(InterruptedException e) { e.printStackTrace(); } } @Then("^verify query result$") public void verifyQueryResult() throws Throwable { // Write code here that turns the phrase above into concrete actions //throw new PendingException(); //判断搜索的结果是否包含期望的关键字 Assert.assertTrue(driver.getPageSource().contains("selenium")); driver.quit(); } }
接着介绍下PMO(Page Object Model)和Page Factory.
在利用WebDriver做UI自动化测试时很多时候会将页面测试元素定位和操作都会放到一个测试文件class里面,当界面出现变动时需要找出所有的页面做修改,而且测试用例的可读性也不强。为了让用例可读性更强和后期用例更易维护,减少代码冗余增加代码利用率,于是出现了PMO. 这次的demo我是用python实现的,后面也附带有java的实现版本。
我们先来看一般的测试baidu search功能的测试用例实现步骤:
def test_serch_mail(): chromedriver="C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe" os.environ["webdriver.chrome.driver"]=chromedriver driver=webdriver.Chrome(chromedriver) url="https://www.baidu.com/" driver.get(url) time.sleep(3) driver.find_element_by_id("kw").clear() driver.find_element_by_id("kw").send_keys("page object") time.sleep(3) driver.find_element_by_id("su").click() time.sleep(3) driver.quit()
这里我们可以看到页面元素定位,操作都在一个文件中,用例的可读性也很差。
我们再来看下通过PMO实现同样的功能:
1.首先我们结合功能需要重写下Selenium2Library的方法:
#-*- coding: utf-8 -*- from selenium.webdriver.support.wait import WebDriverWait from selenium import webdriver class Action(object): def __init__(self, selenium_driver, base_url, pagetitle): self.base_url = base_url self.pagetitle = pagetitle self.driver = selenium_driver #打开页面,校验页面链接是否加载正确 def _open(self, url, pagetitle): #使用get打开访问链接地址 self.driver.get(url) self.driver.maximize_window() #使用assert进行校验,打开的链接地址是否与配置的地址一致。调用on_page()方法 assert self.on_page(pagetitle), u"打开开页面失败 %s" #重写元素定位方法 def find_element(self,*loc): #return self.driver.find_element(*loc) try: WebDriverWait(self.driver,10).until(lambda driver: driver.find_element(*loc).is_displayed()) return self.driver.find_element(*loc) except: print u"%s 页面中未能找到 %s 元素"%(self, loc) #重写switch_frame方法 def switch_frame(self, loc): return self.driver.switch_to_frame(loc) #定义open方法,调用_open()进行打开链接 def open(self): self._open(self.base_url, self.pagetitle) #使用current_url获取当前窗口Url地址,进行与配置地址作比较,返回比较结果(True False) def on_page(self, pagetitle): return pagetitle in self.driver.title #定义script方法,用于执行js脚本,范围执行结果 def script(self, src): self.driver.execute_script(src) #重写定义send_keys方法 def send_keys(self, loc, vaule, clear_first=True, click_first=True): try: loc = getattr(self,"_%s"% loc) if click_first: self.find_element(*loc).click() if clear_first: self.find_element(*loc).clear() self.find_element(*loc).send_keys(vaule) except AttributeError: print u"%s 页面中未能找到 %s 元素"%(self, loc)
2.接着定义一个searchpage.py文件来存放element location和element operator:
# coding: utf-8 _author_='jessica' from selenium.webdriver.common.by import By import BasePage class SearchPage(BasePage.Action): searchtest_loc=(By.ID,"kw") searchbutton_loc=(By.ID,"su") def open(self): self._open(self.base_url,self.pagetitle) def input_searchtext(self,searchtxt): self.find_element(*self.searchtest_loc).send_keys(searchtxt) def click_submit(self): self.find_element(*self.searchbutton_loc).click()
3.然后我们利用PMO的思想来实现baidu搜索的功能, 代码末尾加入了生成HTML报告的功能.这里我们可以看到用例测试功能可读性更强,测试数据暴露在用例里面, 测试文件里面只包含测试步骤。页面的元素定位和操作在page object文件中。这样当页面发生变化时需要修改一处不用更新所有涉及的文件,这样维护起来更方便。
# coding: utf-8 _author_='jessica' import sys reload(sys) sys.setdefaultencoding('utf-8') import unittest import SearchPage from selenium import webdriver import time import HtmlTestRunner class CaseSearchtxt(unittest.TestCase): @classmethod def setUpClass(cls): # chromedriver = "C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe" # os.environ["webdriver.chrome.driver"] = chromedriver cls.driver=webdriver.Chrome() cls.driver.implicitly_wait(30) cls.url="https://www.baidu.com/" cls.searchtxt="POM" def test_search(self): Search_Page=SearchPage.SearchPage(self.driver,self.url,u"百度一下,你就知道") Search_Page.open() Search_Page.input_searchtext(self.searchtxt) time.sleep(3) Search_Page.click_submit() time.sleep(3) def test_run1(self): self.assertIs(1,1 @classmethod def tearDownClass(cls): cls.driver.quit() if __name__=='__main__': test_suite=unittest.TestSuite() # test_suite.addTest(CaseSearchtxt('test_search')) test_suite.addTest(CaseSearchtxt('test_run1')) fp=open('res.html','wb') runner=HtmlTestRunner.HTMLTestRunner(stream=fp,report_title='test report',descriptions='test situation') runner.run(test_suite)
下面代码展示的是用java来实现PMO和Page Factory:验证成功登录guru99网站. 完整的Project结构如下图:
先申明两个page object. Guru99Login和GuruHomePage.
其中Guru99Login:
package pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class Guru99Login { WebDriver driver; By use99GuruName=By.name("uid"); By password99Guru=By.name("password"); By titleText=By.className("barone"); By login =By.name("btnLogin"); public Guru99Login(WebDriver driver){ this.driver=driver; } //Set user name in textbox public void setUserName(String strUserName){ driver.findElement(use99GuruName).sendKeys(strUserName); } //Set password in password textbox public void setPassword(String strPassword){ driver.findElement(password99Guru).sendKeys(strPassword); } public void clickLogin(){ driver.findElement(login).click(); } public String getLoginTitle(){ return driver.findElement(titleText).getText(); } public void loginToGuru99(String strUserName,String strPassword) { this.setUserName(strUserName); this.setPassword(strPassword); this.clickLogin(); } }
其中GuruHomePage:
package pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class Guru99HomePage { WebDriver driver; By homePageUserName=By.xpath("//table//tr[@class='heading3']/td"); public Guru99HomePage(WebDriver driver){ this.driver=driver; } public String getHomePageDashboardUserName(){ return driver.findElement(homePageUserName).getText(); } }
测试用例Test99GuruLogin
package test; import java.util.concurrent.TimeUnit; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import pages.Guru99Login; import pages.Guru99HomePage; public class Test99GuruLogin { WebDriver driver; Guru99Login objLogin; Guru99HomePage objHomePage; @BeforeTest public void setup(){ driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS); driver.get("http://demo.guru99.com/V4/"); } @Test(priority = 0) public void test_Home_Page_Appear_Correct(){ objLogin=new Guru99Login(driver); String loginPageTitle=objLogin.getLoginTitle(); Assert.assertTrue(loginPageTitle.toLowerCase().contains("guru99 bank")); objLogin.loginToGuru99("mgr123","mgr!23"); objHomePage = new Guru99HomePage(driver); Assert.assertTrue(objHomePage.getHomePageDashboardUserName().toLowerCase().contains("mgr123")); } @AfterTest public void tearDown(){ driver.quit(); } }
然后我们再来看下运用PageFactory的实现, 可以通过@FindBy来定位元素,initElements来初始化元素。
引用PageFactory来定义Login和Home Page:
其中Guru99Login:
package PageFactory; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class Guru99Login { WebDriver driver; @FindBy(name="uid") WebElement use99GuruName; @FindBy(name="password") WebElement password99Guru; @FindBy(className="barone") WebElement titleText; @FindBy(name="btnLogin") WebElement login; public Guru99Login(WebDriver driver){ this.driver=driver; PageFactory.initElements(driver,this); } //Set user name in textbox public void setUserName(String strUserName){ use99GuruName.sendKeys(strUserName); } //Set password in password textbox public void setPassword(String strPassword){ password99Guru.sendKeys(strPassword); } public void clickLogin(){ login.click(); } public String getLoginTitle(){ return titleText.getText(); } public void loginToGuru99(String strUserName,String strPassword) { this.setUserName(strUserName); this.setPassword(strPassword); this.clickLogin(); } }
其中Guru99HomePage:
package PageFactory; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class Guru99HomePage { WebDriver driver; @FindBy(xpath = "//table//tr[@class='heading3']/td") WebElement homePageUserName; public Guru99HomePage(WebDriver driver){ this.driver=driver; PageFactory.initElements(driver,this); } public String getHomePageDashboardUserName(){ return homePageUserName.getText(); } }
测试用例Test99GuruLoginWithPageFactory
package test; import java.util.concurrent.TimeUnit; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import pages.Guru99Login; import pages.Guru99HomePage; public class Test99GuruLoginWithPageFactory { WebDriver driver; Guru99Login objLogin; Guru99HomePage objHomePage; @BeforeTest public void setup(){ driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS); driver.get("http://demo.guru99.com/V4/"); } @Test(priority = 0) public void test_Home_Page_Appear_Correct(){ objLogin=new Guru99Login(driver); String loginPageTitle=objLogin.getLoginTitle(); Assert.assertTrue(loginPageTitle.toLowerCase().contains("guru99 bank")); objLogin.loginToGuru99("mgr123","mgr!23"); objHomePage = new Guru99HomePage(driver); Assert.assertTrue(objHomePage.getHomePageDashboardUserName().toLowerCase().contains("mgr123")); } @AfterTest public void tearDown(){ driver.quit(); } }