自动化测试Junit,TestNg, DDT,BDD, PMO介绍

博客很久没更新了,最近在研究python PMO, 趁机给java自动化相关的知识点做个总结。

先说Junit,Testng. 这两个都是用来和java配合做自动化单元测试的框架, Testgn介于Junit3和Junit4之间。但是总的来说Testng是优于Junit. 主要表现在以下几个方面:

1.Testng支持更多的标签:

自动化测试Junit,TestNg, DDT,BDD, PMO介绍_第1张图片

2.在套件测试方面,Testng引入了组的概念,执行套件测试会更灵活。

3.Testng利用dependOnMethods实现依赖测试,Junit目前还不支持。

自动化测试Junit,TestNg, DDT,BDD, PMO介绍_第2张图片

再介绍下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();
    }

}
View Code

由于近来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
View Code

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();
    }
}
View Code

接着介绍下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()
View Code

这里我们可以看到页面元素定位,操作都在一个文件中,用例的可读性也很差。

我们再来看下通过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)
View Code

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()
View Code

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)
View Code

下面代码展示的是用java来实现PMO和Page Factory:验证成功登录guru99网站. 完整的Project结构如下图:

自动化测试Junit,TestNg, DDT,BDD, PMO介绍_第3张图片

先申明两个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();
    }
}
View Code

其中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();
    }
}
View Code

测试用例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();
    }
}
View Code

然后我们再来看下运用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();
    }
}
View Code

其中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();
    }
}
View Code

测试用例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();
    }
}
View Code

 

你可能感兴趣的:(自动化测试Junit,TestNg, DDT,BDD, PMO介绍)