Ethon

为什么要有方法,因为懒惰是一种美德。

   :: 首页  :: 新随笔  ::  ::  :: 管理

Selenium WebDriver 数据驱动测试框架,以QQ邮箱添加联系人为示例,测试框架结构如下图:

ObjectMap.java

/**
 * 使用配置文件存储测试页面上的定位和定位表达式,做到定位数据和程序的分离
 */
import java.io.FileInputStream;
import java.io.IOException;
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 (IOException e) {
            System.out.println("读取对象文件出错");
            e.printStackTrace();
        }
    }

    public By getLocator(String ElementNameInpopFile) throws Exception {
        // 根据变量ElementNameInpopFile,从属性配置文件中读取对应的配置对象
        String locator = properties.getProperty(ElementNameInpopFile);
        
        // 将配置对象中的定位类型存储到locatorType变量,将定位表达式的值存储到locatorValue变量中
        String locatorType = locator.split(":")[0];
        String locatorValue = locator.split(":")[1];
        
        // 在Eclipse中的配置文件均默认为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.className(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("输入的 locator type 未在程序中被定义:" + locatorType);
        }
    }
}

Constant.java

public class Constant {
    
    //测试网址常量
    public static final String URL = "http://mail.qq.com";

    //测试数据EXCEL路径
    public static final String TestDataExcelFilePath = "f:\\QQ邮箱的测试数据.xlsx";
    
    //EXCEL测试数据sheet名称
    public static final String  TestDataExcelFileSheet = "新建联系人测试用例";
}

ExcelUntil.java

package until;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class ExcelUntil {

    private static XSSFSheet excelWSheet;
    private static XSSFWorkbook excelWBook;
    private static XSSFCell cell;
    private static XSSFRow row;
    
    //指定要操作的excel文件的路径及sheet名称
    public static void setExcelFile(String path,String sheetName) throws Exception{
        
        FileInputStream excelFile;
        try {
            excelFile = new FileInputStream(path);
            excelWBook = new XSSFWorkbook(excelFile);
            excelWSheet = excelWBook.getSheet(sheetName);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    //读取excel文件指定单元格数据(此方法只针对.xlsx后辍的Excel文件)
    public static String getCellData(int rowNum,int colNum) throws Exception{
        try {
            //获取指定单元格对象
            cell = excelWSheet.getRow(rowNum).getCell(colNum);
            //获取单元格的内容
            //如果为字符串类型,使用getStringCellValue()方法获取单元格内容,如果为数字类型,则用getNumericCellValue()获取单元格内容
            String cellData = cell.getStringCellValue();
            return cellData;    
        } catch (Exception e) {
            return "";
        }
    }
    
    //在EXCEL的执行单元格中写入数据(此方法只针对.xlsx后辍的Excel文件) rowNum 行号,colNum 列号
    public static void setCellData(int rowNum,int colNum,String Result) throws Exception{
        try {
            //获取行对象
            row = excelWSheet.getRow(rowNum);
            //如果单元格为空,则返回null
            cell = row.getCell(colNum);
            if(cell == null){
                cell=row.createCell(colNum);
                cell.setCellValue(Result);
            }else{
                cell.setCellValue(Result);
            }
            FileOutputStream out = new FileOutputStream(Constant.TestDataExcelFilePath);
            //将内容写入excel中
            excelWBook.write(out);
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    //从EXCEL文件中获取测试数据
    public static Object[][] getTestData(String excelFilePath,String sheetName) throws IOException{
        //声明一个file文件对象
        File file = new File(excelFilePath);
        //创建一个输入流
        FileInputStream in = new FileInputStream(file);
        //声明workbook对象
        Workbook workbook = null;
        //判断文件扩展名
        String fileExtensionName = excelFilePath.substring(excelFilePath.indexOf("."));
        if(fileExtensionName.equals(".xlsx")){
            workbook = new XSSFWorkbook(in);
        }else {
            workbook = new HSSFWorkbook(in);
        }
        
        //获取sheet对象
        Sheet sheet = workbook.getSheet(sheetName);
        //获取sheet中数据的行数,行号从0始
        int rowCount = sheet.getLastRowNum()-sheet.getFirstRowNum();
        
        List<Object[]> records = new ArrayList<Object[]>();
        //读取数据(省略第一行表头)
        for(int i=1; i<rowCount+1; i++){
            //获取行对象
            Row row = sheet.getRow(i);
            System.out.println(">>>>>>>>>>> "+ row.getLastCellNum());
            //声明一个数组存每行的测试数据,excel最后两列不需传值
            String[] fields = new String[row.getLastCellNum()-2];
            //excel倒数第二列为Y,表示数据行要被测试脚本执行,否则不执行
            if(row.getCell(row.getLastCellNum()-2).getStringCellValue().equals("Y")){
                for(int j=0; j<row.getLastCellNum()-2; j++){
                    //判断单元格数据是数字还是字符
                    //fields[j] = row.getCell(j).getCellTypeEnum() == CellType.STRING ? row.getCell(j).getStringCellValue() : ""+row.getCell(j).getNumericCellValue(); 
                    fields[j] = row.getCell(j).getCellType() == CellType.STRING ? row.getCell(j).getStringCellValue() : ""+row.getCell(j).getNumericCellValue(); 
                }
                records.add(fields);
            }
        }
        //将list转为Object二维数据
        Object[][] results = new Object[records.size()][];
        //设置二维数据每行的值,每行是一个object对象
        for(int i=0; i<records.size(); i++){
            results[i]=records.get(i);
        }
        return results;
    }
    
    public static int getLastColumnNum(){
        //返回数据文件最后一列的列号,如果有12列则返回11
        return excelWSheet.getRow(0).getLastCellNum()-1;
    }
}

Log.java

package until;

import org.apache.log4j.Logger;

public class Log {

    // 初始化Log4j日志
    private static Logger Log = Logger.getLogger(Log.class.getName());

    // 打印测试用例开头的日志
    public static void startTestCase(String sTestCaseName) {
        Log.info("------------------ " + sTestCaseName + "  " +"开始执行 ------------------");
    }

    //打印测试用例结束的日志
    public static void endTestCase(String sTestCaseName) {
        Log.info("------------------ " + sTestCaseName + "  " +"测试执行结束 ---------------");

    }

    public static void info(String message) {
        Log.info(message);
    }

    public static void warn(String message) {
        Log.warn(message);
    }

    public static void error(String message) {
        Log.error(message);
    }

    public static void fatal(String message) {
        Log.fatal(message);
    }

    public static void debug(String message) {
        Log.debug(message);
    }

}

 

LoginPage.java

package pageobject;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

import until.ObjectMap;

public class LoginPage {
    
    private WebElement element = null;
    //指定页面元素定位表达式配置文件的绝对路径
    private ObjectMap objectMap = new ObjectMap("F:\\workspace\\TestNGProj\\ObjectMap.properties");
    private WebDriver driver;
    
    public LoginPage(WebDriver driver){
        this.driver = driver;
    }
    
    //返回登录页面中的用户名输入框页面元素对象
    public WebElement username() throws Exception{
        element =driver.findElement(objectMap.getLocator("QQ.Email.username"));
        return element;
    }
    
    //返回登录页面中的密码输入框页面元素对象
    public WebElement password() throws Exception {
        element = driver.findElement(objectMap.getLocator("QQ.Email.password"));
        return element;
    }
    
    //返回登录页面中的登录按钮页面元素对象
    public WebElement login_button() throws Exception {
        element = driver.findElement(objectMap.getLocator("QQ.Email.login_button"));
        return element;
    } 
}

 

HomePage.java

package pageobject;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

import until.ObjectMap;

public class HomePage {
    
    private WebElement element = null;
    private ObjectMap objectMap = new ObjectMap("F:\\workspace\\TestNGProj\\ObjectMap.properties");
    private WebDriver driver;
    
    public HomePage(WebDriver driver){
        this.driver = driver;
    }
    
    //获取登录后主页的“通讯录”链接
    public WebElement addressLink() throws Exception{
        element = driver.findElement(objectMap.getLocator("QQEmail.homepage.address_book"));
        return element;
    }
}

 

AddressBookPage.java

package pageobject;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

import until.ObjectMap;

public class AddressBookPage {
    
    private WebElement element = null;
    private ObjectMap objectMap = new ObjectMap("F:\\workspace\\TestNGProj\\ObjectMap.properties");
    private WebDriver driver;
    
    public AddressBookPage(WebDriver driver){
        this.driver = driver;
    }
    
    //获取新建联系人按钮
    public WebElement addContactButton() throws Exception{
        element = driver.findElement(objectMap.getLocator("QQEmail.addressBook.add_button"));
        return element;
    }
    
    //新建联系人页面姓名输入框
    public WebElement addContactName()throws Exception{
        element = driver.findElement(objectMap.getLocator("QQEmail.addressBook.add_Contact"));
        return element;
    }
    
    //新建联系人页面邮件输入框
    public WebElement addContactEmail() throws Exception{
        element = driver.findElement(objectMap.getLocator("QQEmail.addressBook.add_email"));
        return element;
    }
    
    //新建联系人页面电话输入框
    public WebElement addContactTell() throws Exception{
        element = driver.findElement(objectMap.getLocator("QQEmail.addressBook.add_tell"));
        return element;
    }
    
    //新建联系人页面国家输入框
    public WebElement addContactCounty() throws Exception{
        element = driver.findElement(objectMap.getLocator("QQEmail.addressBook.add_country"));
        return element;
    }
    
    //新建联系人页面省份输入框
    public WebElement addContactProvince() throws Exception{
        element = driver.findElement(objectMap.getLocator("QQEmail.addressBook.add_province"));
        return element;
    }
    
    //新建联系人页面城市输入框
    public WebElement addContactCity() throws Exception{
        element = driver.findElement(objectMap.getLocator("QQEmail.addressBook.add_city"));
        return element;
    }
    
    //新建联系人页面保存按钮
    public WebElement addContactSaveButton() throws Exception{
        element = driver.findElement(objectMap.getLocator("QQEmail.addressBook.save_button"));
        return element;
    }
}

 

LoginAction.java

package appmodules;

import org.openqa.selenium.WebDriver;
import org.testng.annotations.Test;
import pageobject.LoginPage;
import until.Log;

/**
 * 登录方法的封装,方便其他测试脚本的调用
 *
 */
public class LoginAction {

    public static void execute(WebDriver driver,String userName,String passWord) throws Exception{
        Log.info("访问网址:http://mail.qq.com");
        driver.get("http://mail.qq.com");
        driver.switchTo().frame("login_frame");
        LoginPage loginPage = new LoginPage(driver);
        loginPage.username().clear();
        Log.info("在QQ邮箱登录页面的用户名输入框中输入 "+userName);
        loginPage.username().sendKeys(userName);
        Log.info("在QQ邮箱登录页面的密码输入框中输入 "+passWord);
        loginPage.password().sendKeys(passWord);
        Log.info("单击登录页面的登录按钮");
        loginPage.login_button().click();
        //Thread.sleep(5000);
    }
}

 

AddContactAction.java

package appmodules;

import org.openqa.selenium.WebDriver;
import pageobject.AddressBookPage;
import pageobject.HomePage;
import until.Log;

public class AddContactAction {
    
    public static void execute(
            WebDriver driver,
            String userName,
            String passWord,
            String contactName,
            String contactEmail,
            String contactCountry,
            String contactProvince,
            String contactCity) throws Exception{
        //调用登录方法
        Log.info("调用LoginAction类的execute方法");
        LoginAction.execute(driver, userName, passWord);
        Thread.sleep(3000);
        
        HomePage homePage = new HomePage(driver);
        Log.info("登录后,单击通讯录链接");
        homePage.addressLink().click();
        driver.switchTo().frame("mainFrame");
        
        AddressBookPage addressBookPage = new AddressBookPage(driver);
        Log.info("休眠3秒,等待打开通讯录页面");
        Thread.sleep(3000);
        
        Log.info("在通讯录页面,单击'新增联系人'按钮");
        addressBookPage.addContactButton().click();
        
        Log.info("在联系人姓名输入框中,输入: "+contactName);
        addressBookPage.addContactName().sendKeys(contactName);
        Log.info("在联系人邮箱输入框中,输入: "+contactEmail);
        addressBookPage.addContactEmail().sendKeys(contactEmail);
        //addressBookPage.addContactTell().sendKeys(contactTell);
        Log.info("在联系人国家输入框中,输入: "+contactCountry);
        addressBookPage.addContactCounty().sendKeys(contactCountry);
        Log.info("在联系人省份输入框中,输入: "+contactProvince);
        addressBookPage.addContactProvince().sendKeys(contactProvince);
        Log.info("在联系人城市输入框中,输入: "+contactCity);
        addressBookPage.addContactCity().sendKeys(contactCity);
        Log.info("单击确定按钮");
        addressBookPage.addContactSaveButton().click();
        Log.info("休眠5秒,等待保存联系人后返回通讯录的主页面");
        Thread.sleep(5000);
    }
}

TestQQEmailAddContact.java

package testscript;

import java.io.IOException;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import appmodules.AddContactAction;
import until.Constant;
import until.ExcelUntil;
import until.Log;

public class TestQQEmailAddContact {
    
    public WebDriver driver;
    //调用Constant类中的常量url
    private String url = Constant.URL;
    
    @DataProvider(name="testData")
    public static Object[][] data() throws IOException{
        //调用ExcelUntil工具类中getTestData()方法获取测试数据
        return ExcelUntil.getTestData(Constant.TestDataExcelFilePath, Constant.TestDataExcelFileSheet);
    }
    
    //使用名称为testData的dataProvider作为测试方法的测试数据集
    //测试方法一共有12个参数,分别对应Excel数据文件中的1~12列
    @Test(dataProvider="testData")
    public void testAddressBook(
            String caseRowNumber,
            String testCaseName,
            String userName,
            String passWord,
            String contactName,
            String contactEmail,
            String contactTell,
            String contactCountry,
            String contactProvince,
            String contactCity,
            String assertContactName,
            String assertContactEmail
            ) throws Exception{
        Log.startTestCase(testCaseName);
        driver.get(url);
        
        Log.info("调用AddContactAction类的execute方法");
        try {
            AddContactAction.execute(driver, userName, passWord, contactName, contactEmail, contactCountry, contactProvince, contactCity);
        } catch (AssertionError error) {
            Log.info("添加联系人失败");
            //设置Excel中测试数据行的执行结果为“测试执行失败”
            ExcelUntil.setCellData(Integer.parseInt(caseRowNumber.split("[.]")[0]), ExcelUntil.getLastColumnNum(), "测试执行失败");
            Assert.fail("执行AddContactAction类的execute方法失败");
        }
        Log.info("调用AddContactAction类的execute方法后,休眠3秒钟");
        Thread.sleep(3000);
        
        Log.info("断言通讯录页面是否包含联系人姓名关键字");
        try {
            Assert.assertTrue(driver.getPageSource().contains(assertContactName));
        } catch (AssertionError error) {
            Log.info("断言通讯录页面是否包含联系人姓名的关键字失败");
            ExcelUntil.setCellData(Integer.parseInt(caseRowNumber.split("[.]")[0]), ExcelUntil.getLastColumnNum(), "测试执行失败");
            Assert.fail("断言通讯录页面是否包含联系人姓名的关键字失败");
        }
        
        Log.info("断言通讯录页面是否包含联系人邮箱关键字");
        try {
            Assert.assertTrue(driver.getPageSource().contains(assertContactEmail));
        } catch (AssertionError error) {
            Log.info("断言通讯录页面是否包含联系人邮箱的关键字失败");
            ExcelUntil.setCellData(Integer.parseInt(caseRowNumber.split("[.]")[0]), ExcelUntil.getLastColumnNum(), "测试执行失败");
            Assert.fail("断言通讯录页面是否包含联系人邮箱的关键字失败");
        }
        
        Log.info("新建联系人全部断言成功,在Excel的测试数据文件的'测试执行结果'中写入'测试执行成功'");
        //断言全部成功,在Excel的测试数据文件的“测试执行结果”中写入“测试执行成功”
        ExcelUntil.setCellData(Integer.parseInt(caseRowNumber.split("[.]")[0]), ExcelUntil.getLastColumnNum(), "测试执行成功");
        Log.info("测试结果成功写入excel数据文件中的测试执行结果列");
        Log.endTestCase(testCaseName);

    }
    
    @BeforeMethod
    public void beforeMethod(){
        System.setProperty("webdriver.chrome.driver", "e:\\chromedriver.exe");
        driver = new ChromeDriver();
    }
    
    @AfterMethod
    public void afterMethod(){
        driver.quit();
    }

    @BeforeClass
    public void BeforeClass() throws Exception{
        ExcelUntil.setExcelFile(Constant.TestDataExcelFilePath,Constant.TestDataExcelFileSheet);
    }
}

 

ObjectMap.properties

 

QQ邮箱的测试数据.xlsx

 

个人微信订阅号:专注测试开发、自动化测试。

 

posted on 2019-05-20 14:32  Ethon  阅读(2117)  评论(1编辑  收藏  举报