亲手教你WebUI自动化框架从零开始搭建

本文详细介绍了使用Selenium进行WebUI自动化测试的框架设计,包括对象库层、核心功能实现(如driver封装、页面元素操作、失败处理)、逻辑层的PageFactory模式、业务层的测试用例编写,以及如何通过TestNG执行测试并利用Jenkins进行持续集成,提供了代码示例和测试报告生成方法。
摘要由CSDN通过智能技术生成

一、设计思路
PO模式

对象库层:二次封装Selenium的方法。 core:主要封装driver方法,并加入日志、失败截图
页面操作层(逻辑层):元素对象和元素操作的封装。page:封装页面的元素对象和元素操作
业务层:测试用例的操作部分。 test: 业务测试,使用testng框架执行测试用例
二、代码层级结构

代码层级如下:
.
├── README.md
├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── selenium
│   │   │           └── webui
│   │   │               ├── Browser.java       浏览器类型枚举
│   │   │               ├── LocatorType.java   定位方式类型枚举
│   │   │               ├── core
│   │   │               │   ├── Config.java    加载环境配置文件,设置浏览器driver驱动参数
│   │   │               │   ├── DriverManager.java   driver能力封装(点击、滚动、跳转、输入、元素定位查找检查、实现失败处理接口、异常截图等)
│   │   │               │   ├── FailureAction.java   失败处理接口--截图功能 
│   │   │               │   └── WebDriverFactory.java  按浏览器类型创建driver
│   │   │               ├── page
│   │   │               │   ├── HomeSearchPage.java  页面类:继承page,定义页面元素、方法
│   │   │               │   ├── Page.java   基础页面:加载PO,页面元素初始化
│   │   │               │   └── ReturnValue.java  
│   │   │               └── utils
│   │   │                   ├── Constants.java
│   │   │                   ├── FileManager.java   文件处理:查找文件是否存在,删除文件
│   │   │                   ├── JsonFileParser.java  json文件处理
│   │   │                   ├── ResourcePathParser.java 读取path
│   │   │                   ├── SshCmd.java   执行ssh,并执行命令
│   │   │                   └── Util.java   工具类:加载配置文件、日期获取、等待、js脚本
│   │   └── resources
│   │       ├── application.properties  配置文件
│   │       ├── log4j.properties  log4j配置文件
│   │       ├── testng.xml  测试用例集
│   │       └── webdriver   
│   │           ├── IEDriverServer.exe
│   │           ├── chromedriver
│   │           ├── chromedriver.exe
│   │           ├── geckodriver
│   │           ├── geckodriver_0.11.0.exe
│   │           └── geckodriver_0.17.0.exe
│   └── test
│       └── java
│           └── com
│               └── selenium
│                   └── webui
│                       ├── TestPage.java  基础页面测试类:BeforeClass/AfterClass操作
│                       └── page
│                           └── TestHomeSearchPage.java  测试页面类继承TestPage:具体测试用例

三、核心功能实现

1.工具类:

// Load properties: application.properties.
    public static Properties loadProperties(String path){
        try{
            InputStream is = Util.class.getClassLoader().getResourceAsStream(path);
            if (is != null){
                properties.load(is);
            }
        } catch (IOException e){
            e.printStackTrace();
            logger.error(e.getMessage());
        }
        return properties;
    }
 
    public static String getProperty(String path, String pName){
        Properties properties = loadProperties(path);
        return (String)properties.get(pName);
    }

2.对象库层

// selenium的二次封装
		//选择浏览器,创建driver
    public static WebDriver createWebDriver(Browser browser){
        WebDriver driver;
        Properties properties;
        final String propertyPath;
        propertyPath  = "application.properties";
        properties = Util.loadProperties(propertyPath);
        switch (browser){
            case CHROME:
                driver = new ChromeDriver(Config.getChromeOptions());
                break;
            case IE:
            	DesiredCapabilities cap=DesiredCapabilities.internetExplorer();
            	cap.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
            	System.setProperty("webdriver.ie.driver", properties.getProperty("ie.webdriver.driver"));
                driver = new InternetExplorerDriver(cap);
                break;
            case EDGE:
                driver = new EdgeDriver();
                break;
            case FIREFOX:
            default:
                //driver = new FirefoxDriver(Config.getFirefoxProfile());
            	System.setProperty("webdriver.gecko.driver", properties.getProperty("ff.webdriver.gecko.driver"));
            	//System.setProperty("webdriver.firefox.marionette", properties.getProperty("ff.webdriver.gecko.driver"));
            	driver = new FirefoxDriver();
        }
        driver.manage().timeouts().implicitlyWait(Config.WAIT_FOR_TIMEOUT, TimeUnit.SECONDS);
        driver.manage().window().maximize();
        return driver;
    }
	//DriverManager.java
	// driver Capabilities
	public void navigateTo(String url) {
		logger.info("Navigate to: " + url + " to build Page: ");
		try {
			driver.get(url);
			Thread.sleep(SLEEP_DURATION);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e.getMessage());
			screenshot("Exception_navigateTo");
		}
	}
	
		public void click(WebElement we, int retries) {
		logger.info("click by: " + we);
		if (retries < MAX_RETRIES) {
			try {
				we.click();
				implicitlyWait(60);
			} catch (Exception e) {
				e.printStackTrace();
				screenshot("Exception_click");
				logger.info(e.getMessage());
				long waitTime = (1 << retries++) * 1000;
				logger.info("Retries: " + retries + " after " + waitTime
						+ " milliseconds");
				Util.sleep(waitTime);
				click(we, retries);
				throw e;
			}
		}
	}

3.逻辑层

  • 定义页面元素,并在类加载时调用initElements方法实现元素初始化
// PageFactory模式
    public static <T> T initPage(Class<T> clz) {
        logger.info("init page: " + clz.getSimpleName() + " begin...");
        T page = PageFactory.initElements(manager.getDriver(), clz);
        logger.info("init page: " + clz.getSimpleName() + " done!");
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
            logger.info(e.getMessage());
        }
        return page;
    }
 
public class HomeSearchPage extends Page {
	private static final Logger logger = Logger.getLogger(HomeSearchPage.class);
 
	@FindBy(id = "states-autocomplete")
	private WebElement searchBox;
 
	@FindBy(xpath = "//div[@class=\"item item-type-103\"][1]")
	private WebElement selectKeyword;
 
	@FindBy(xpath = "//div[text()=\"搜索民宿\"]")
	private WebElement searchButton;
  • 页面健康检查,页面类中被FindBy注解的字段都会检查是否存在
      public boolean healthCheck() {
        boolean flag = true;
        for (Field field : this.getClass().getDeclaredFields()) {
            if (field.isAnnotationPresent(FindBy.class)) {
                field.setAccessible(true);
                try {
                    if (!manager.weIsDisplayed((WebElement)(field.get(this)))) {
                        flag = false;
                    }
                } catch (Exception e) {
                    flag = false;
                    logger.warn(e.getMessage());
                    e.printStackTrace();
                }
            }
        }
        return flag;
    }

4.业务层

    @Parameters({"words", "browser"})
    public void testSearch(String words, String browser) {
    	logger.debug(Constants.REG+"testSearch"+Constants.REG);
//        page = ((LoginPage)page).login(userId, password);
    	HomePage homepage = Page.initPage(HomePage.class);
        ReturnValue rv = homepage.search(words, browser);
        logger.info(page);
       // page = rv.getPage();
        Assert.assertEquals(rv.getError(), SUCCESS);
    }

参数化:testng的@Parameters读取testng.xml中参数

四、测试用例执行和测试报告

         // pom.xml
					<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.20</version>
                <configuration>
                    <runOrder>alphabetical</runOrder>
                    <suiteXmlFiles>
                        <suiteXmlFile>src/main/resources/testng.xml</suiteXmlFile>
                    </suiteXmlFiles>
                    <properties>
                        <property>
                            <name>usedefaultlisteners</name>
                            <value>false</value>
                        </property>
                        <property>
                            <name>listener</name>
                            <value>org.uncommons.reportng.HTMLReporter,org.uncommons.reportng.JUnitXMLReporter</value>
                        </property>
                    </properties>
                    <forkMode>once</forkMode>
 
                </configuration>
            </plugin>
            
    // testng.xml        
    <listeners>
        <listener class-name="org.uncommons.reportng.HTMLReporter"/>
        <listener class-name="org.uncommons.reportng.JUnitXMLReporter"/>
    </listeners>
    <classes>
        <class name="com.selenium.webui.page.TestHomeSearchPage">
            <methods>
                <include name="testSelectKeyword"/>
                <include name="testSelectCity"/>
            </methods>
        </class>
    </classes>
    <test name ="Teardown Test" preserve-order="true" >
        <classes>
            <class name = "com.selenium.webui.TestPage">
                <methods>
                    <include name="shutDown"/>
                </methods>
            </class>
        </classes>
    </test>
 
    <parameter name="host" value="inn.ctrip.com/onlineinn/index" />
    <parameter name="browser" value="chrome"/>
    <parameter name="words" value="迪士尼"/>

pom.xml中加入插件,使用mvn install clean运行testng.xml中的测试用例

报告目录:test-output/html/index.html

五、持续集成

1.Jenkins安装插件:TestNG Results Plugin

2.创建job运行脚本

“构建后操作”->“Publish TestNG Results”

3.查看报告

 学习安排上
如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助,朋友们如果需要可以自行免费领取 【保证100%免费】

视频文档获取方式:

这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方小卡片即可自行领取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值