@Author: Basil Guo @Date: Feb. 20, 2021 @Description: Web自动化测试 @Keyword: test, auto, web @Type: tutorial
1. 自动化测试
自动化测试与手工测试相比,最大的一个区别是要求测试人员掌握一门脚本开发语言。自动化测试通俗地讲就是使用软件A自动执行测试用例来测试软件B。软件A既可以是现有的自动化测试工具,也可以是自己编写的测试脚本。软件B就是待测试软件。
自动化测试不见得一定可以提升测试效率,以下场景不适合自动化测试:
- 永远不会再重复的测试流程。
- 项目工期非常短的需求。
- UI的易用性等测试。
- 软硬件结合场景。
1.1 分类
1.1.1 根据测试阶段划分
- 单元自动化测试。单元自动化测试是指通过自动化手段对软件最小可测单元(模块)进行的测试。一个最小可测单元通常为一个方法或函数。单元自动化测试常用的工具(框架)有JUnit、TestNG、Jtest、unittest和Pytest等。
- 集成自动化测试。集成自动化测试是指通过自动化手段把软件的模块组合起来测试。集成测试分为增量测试和非增量测试两种,这两种测试在手工或自动化的集成测试中都可以采用。集成自动化测试的主要表现之一为接口自动化测试,用于接口自动化测试的常用工具(框架)有JMeter、HttpClient、requests、SoapUI和Postman等。
- 在增量测试中,如果增量方式是自顶向下的,那么测试的过程需要桩﹔如果增量方式是自底向上的,那么测试的过程需要驱动。在实际项目中,经常涉及的“打桩”概念就来自于增量测试。
- 非增量测试不像增量测试那样有严格的增量顺序,因此在非增量测试过程中,可能同时需要桩和驱动,也可能只需要其中一个,或者两者都不需要。
- 系统自动化测试。系统自动化测试是指通过自动化手段,将软件、硬件、操作人员当成一个整体进行测试。系统自动化测试又可分为功能自动化测试、性能自动化测试、安全自动化测试和兼容性自动化测试等。系统自动化测试常用的工具(框架)有很多,比如Testin云测平台就提供了兼容性自动化测试功能,它可以测试App在各种手机上运行是否正常。
1.1.2 根据测试类型划分
- 功能自动化测试。功能自动化测试是指通过自动化手段检查软件能否达到预期功能的测试。主要表现为Web应用、移动应用和桌面应用等软件的界面测试。界面自动化测试的常用工具(框架)有Selenium、Appium、Robot Framework、UFT/QTP和AutoIt等。
- 性能自动化测试。性能自动化测试是指通过自动化手段模拟各种正常、峰值和异常负载条件,从而对系统的各项性能指标进行测试。在性能自动化测试中,JMeter和LoadRunner占据了绝对的统治地位。
- 安全自动化测试。安全自动化测试可理解为通过自动化手段检查软件是否有安全漏洞。安全自动化测试包含前期交互、信息收集、威胁建模、漏洞分析、和测试报告7个阶段。安全自动化测试常用工具(框架)有Metasploit、Burp Suite、Nessus、NMap、sqlmap、Synopsys Defensics和Peach Fuzzer等。
1.1.3 根据静态和动态划分
- 静态自动化测试。静态自动化测试是指通过自动化手段不实际运行软件的测试,比如代码审查、文档测试等。根据编程语言不同,代码审查自动化测试工具(框架)的差异很大。对Java而言,常用的有FindBugs、PMD等。
- 动态自动化测试。动态自动化测试是指通过自动化手段实际运行软件的测试,即通常所说的“软件测试”。动态自动化测试(框架)前面已经介绍很多。
1.2 自动化测试
自动化测试最主要的目的是提高软件的质量,例如需求覆盖率、代码覆盖率、缺陷遗漏率。第二个目的是提高测试的效率,手工测试执行的用例由自动化测试代替,测试效率的提高显而易见。
要实施自动化测试需要有明确的目标、足够的资源、合理的计划。在编写自动化测试时,最重要的事情之一是确保它们是优质的文档。这意味着应描述被测试应用程序的所有部分是如何工作的。或者,换句话说,它应拥有高级别的测试覆盖率。测试文档同时涵盖了回归部分和新功能部分,所以不需要额外的回归测试,测试文档会实时讲述产品是如何工作的。测试代码就成了一份实时的文档。
2. Selenium WebDriver
Selenium 2.0发起的WebDriver和Selenium合并。现在已经到了Selenium 4.0。Selenium 3.0去掉了Selenium Remote Control,只支持Java8+,不再提供默认浏览器支持,需要浏览器官方驱动。
如有需要了解Webdriver,请阅读WebDriver | Selenium。
2.1 Python版
这个搭配Python使用,进行Web自动化测试。
-
安装:
$ pip install selenium Requirement already satisfied: pip in d:\developsoftware\python\python38\lib\site-packages (20.3.1) Collecting pip Downloading pip-21.0.1-py3-none-any.whl (1.5 MB) |████████████████████████████████| 1.5 MB 595 kB/s Installing collected packages: pip Attempting uninstall: pip Found existing installation: pip 20.3.1 Uninstalling pip-20.3.1: Successfully uninstalled pip-20.3.1 Successfully installed pip-21.0.1
-
查看:
$ pip show selenium Name: selenium Version: 3.141.0 Summary: Python bindings for Selenium Home-page: https://github.com/SeleniumHQ/selenium/ Author: UNKNOWN Author-email: UNKNOWN License: Apache 2.0 Location: d:\developsoftware\python\python38\lib\site-packages Requires: urllib3 Required-by:
-
卸载Selenium WebDriver模块,可以执行
pip uninstall selenium
当调用Selenium WebDriver模块中的方法去操纵浏览器和网页元素时,Selenium WebDriver模块还需要加载浏览器的驱动程序,如果不安装浏览器的驱动程序,即便是调用了Selenium Web Driver模块中的方法,也驱动不了浏览器去做相关操作。所以除了把Selenium WebDriver模块安装进来之外,还应该为Selenium WebDriver模块配置浏览器的驱动程序。配置Firefox浏览器的驱动程序geckodriver.exe。去GitHub Mozilla/geckodriver下载Firefox的驱动。Google Chrome的驱动,其它浏览器的驱动参见官网给出的链接。下载完成之后,只需要将这个驱动文件放入PATH环境变量可访问到的目录即可。
from selenium import webdriver
driver = webdriver.Firefox()
如果是在默认安装位置安装的Firefox,那么就可以运行了,如果不是,将会报错:selenium.common.exceptions.SessionNotCreatedException: Message: Expected browser binary location, but unable to find binary in default location, no 'moz:firefoxOptions.binary' capability provided, and no binary flag set on the command line
。需要设置绝对路径
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
options = Options()
options.binary_location = r"D:\Program Files\Mozilla Firefox/firefox.exe"
driver = webdriver.Firefox(options=options, executable_path="D:\DevelopSoftware\Python\Python38/geckodriver.exe")
再次运行即可。如果还报错,可能是Firefox软件更新。。。我的就是。
import time
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
driver = None
def setup():
global driver
options = Options()
options.binary_location = r"D:\Program Files\Mozilla Firefox/firefox.exe"
driver = webdriver.Firefox(
options=options, executable_path="D:\DevelopSoftware\Python\Python38/geckodriver.exe")
driver.maximize_window() # 让窗口最大化
def loginWeb():
global driver
driver.get("http://account.ryjiaoyu.com/log-in") # 打开一个网页
# 等待2s
time.sleep(2)
# 邮箱/用户名
emailInput = driver.find_element_by_xpath("//input[@id='Email']")
emailInput.clear() # 根据XPath查找元素并清理文本
emailInput.send_keys("[email protected]") # 输入文本内容
# 密码
passInput = driver.find_element_by_xpath("//input[@id='Password']")
passInput.clear()
passInput.send_keys("bugmenot")
# 登录
loginBtn = driver.find_element_by_xpath(
"//*[@id='loginForm']/form/div[5]/div/input")
loginBtn.click() # 进行单击操作
driver.quit() # 关闭浏览器
def main():
setup()
loginWeb()
if __name__ == "__main__":
main()
Web自动化测试的工具有很多,例如以前比较流行的QTP(升级版叫UFT),它一直被拿来与Selenium WebDriver作对比。
- 首先,QTP是商业工具,需要付费购买,而SeleniumWebDriver是开源的,无须购买;
- 其次,QTP弱化了测试人员脚本设计能力,而Selenium WebDriver强化了测试人员脚本设计能力。深入比较二者后,越来越多的企业把目光转向了Selenium WebDriver。
2.2 Java版本
Firefox 60版本。Java 1.8+。如果你使用的是早期版本,geckodriver可能无法完全支持,也许会遇到一些错误。使用Maven管理项目。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>SeleniumTestNG</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Mastering Selenium TestNG</name>
<description>A basic Selenium POM file</description>
<properties>
<java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<selenium.version>3.12.0</selenium.version>
<testng.version>6.14.3</testng.version>
<!-- Plugins version -->
<maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
<maven-failsafe-plugin.version>2.21.0</maven-failsafe-plugin.version>
<!-- Configuration variables -->
<threads>1</threads>
</properties>
<dependencies>
<!-- selenium的依赖 -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>${selenium.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-remote-driver</artifactId>
<version>${selenium.version}</version>
<scope>test</scope>
</dependency>
<!-- testng的依赖 -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<!-- 该插件在默认情况下会选取以IT结尾的文件 -->
<!-- 如果类名以TEST结尾,它将会被另一个插件maven-surefire-plugin选取 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-failsafe-plugin.version}</version>
<configuration>
<parallel>methods</parallel> <!-- 方法并发执行 -->
<threadCount>${threads}</threadCount> <!-- 控制线程数量 -->
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
当使用Maven Failsafe插件时,设置为integration-test
的goal节点将确保测试在集成测试阶段执行。设置为verify
的goal节点将确保Failsafe插件可验证在integration-test
阶段执行检查的结果,如果某些内容未通过则无法进行构建。如果没有设置verify
的goal节点,则构建不会失败。
TestNG支持开箱即用的并行线程,这里只需要告诉它如何使用这些线程。这就是Maven Failsafe插件发挥作用的地方。我们将使用它为测试配置并行执行的环境。如果你将TestNG作为依赖项,则此配置将应用于TestNG,无须做任何特别的事情。将<parallel>
节点设置为methods
。这将在项目中搜索有@Test
注释的方法,并将它们全部收集到一个巨大的测试池中。然后,Failsafe插件会从这个池中取出测试并运行它们。并发运行的测试数量取决于有多少线程可用。我们将使用<threadCount>
节点来控制线程数。但是不能控制方法并发执行的先后顺序。因为threads
是Maven属性,所以可以使用-D
开关在命令行上重写它的值。如果不重写它的值,它将使用在POM中设置的值作为默认值。
package com.masteringselenium;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxBinary;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import java.io.File;
/**
* 基本测试使用selenium和testNG
*
* @author [email protected]
* @date 21.2.21 17:33
* @since version 1.0
*/
public class BasicTest {
private WebDriver driver;
private ExpectedCondition<Boolean> pageTitleStartsWith(final String searchString) {
return driver -> driver.getTitle().toLowerCase()
.startsWith(searchString.toLowerCase());
}
private void baiduExampleThatSearchesFor(final String searchString) {
driver.get("http://www.baidu.com");
WebElement searchField = driver.findElement(By.name("wd"));
searchField.clear();
searchField.sendKeys(searchString);
System.out.println("Page title is: " + driver.getTitle());
searchField.submit();
WebDriverWait wait = new WebDriverWait(driver, 10, 1000);
wait.until(pageTitleStartsWith(searchString));
System.out.println("Page title is: " + driver.getTitle());
driver.quit();
}
@BeforeTest
public void setup() {
File pathToBinary = new File("D:\\Program Files\\Mozilla Firefox\\firefox.exe");
FirefoxBinary ffBinary = new FirefoxBinary(pathToBinary);
System.setProperty("webdriver.gecko.driver", "D:\\DevelopSoftware\\Python\\Python38\\geckodriver.exe"); // 这个是驱动
// 控制日志的写,没有讨厌的Firefox自己的报错
System.setProperty(FirefoxDriver.SystemProperty.BROWSER_LOGFILE, "/dev/null");
FirefoxOptions options = new FirefoxOptions();
options.setBinary(ffBinary);
driver = new FirefoxDriver(options);
}
@Test
public void baiduCheeseExample() {
baiduExampleThatSearchesFor("Cheese!");
}
@Test
public void baiduMildExample() {
baiduExampleThatSearchesFor("Milk!");
}
@AfterTest
public void tearDown() {
driver.quit();
}
}
有关驱动加载在Java中还可以使用命令行传递参数。既然使用Maven管理,那么就可以这样使用:mvn clean verify -Dwebdriver.gecko.drver=<PATH_TO_GECKODRIVER_BINARY>
。这些是由Selenium团队做的,这些系统属性的格式为WebDriver.<DRIVER_TYPE>.driver
。但是我们这里使用硬编码的方式,直接在代码中指定了。
因为某些浏览器在同一台电脑上只能安装一个版本,所以在开发用的计算机上先选择某一种浏览器来运行测试可能是个好办法。然后可以使用CI服务器来弥补这个不足,将浏览器的覆盖率纳入考虑范围,作为构建流水线的一部分。先为本地计算机挑选一个带有快速JavaScript引擎的浏览器也许同样是一个好办法。
由于Selenium不具备线程安全,因此还需要编写一些额外代码,以确保各个Selenium实例在其独立的线程中运行,而不会在其他线程中运行。
如果是想关闭某些窗口可以使用driver.close()
,否则WebDriver
API中的“关闭并清理”命令是driver.quit()
。
2.3 无头浏览器
就是可以在后台运行的浏览器。但是主要的两个无头浏览器:PhantomJS不再处于主动开发状态;GhostDriver不再拥有核心维护人员。PhantomJS仍然可用,而且可能依然能让GhostDriver启动并运行。然而,用它们进行测试,会存在一些问题。
- 其渲染引擎已经过时(QTWebkit的旧版本);
- 其JavaScript引擎并未在任何主流浏览器中使用;
- 其工具并不是完全线程安全的。
随着ChromeDriver和FirefoxDriver相继发布了支持后台模式的版本,继续使用PhantomJS就不再有意义了。在PhantomJS的流行时期,它曾是非常强大的工具,但现在它已不再是使用Selenium的有效工具了。
Chrome和Firefox的WebDriver在分别设置其ChromeOptions
和FirefoxOptions
时指定options.setHeadless(true)
即可。
2.4 profile的使用
隔离开三个环境:开发、测试、生产环境,可以使用Maven中不同的<profile>
。
<!-- pom.xml -->
<profiles>
<profile>
<id>selenium</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<modules>
<module>chapter1</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<profile>
中可写内容,同正常的pom.xml
类似。如果你现在激活selenium配置文件,就会只执行Selenium测试。由于已经指定默认生效的<profile>
,所以第二条也是可以的。
$ mvn clean verify -Pselenium
$ mvn clean verify
还可以,通过以下命令专门阻止Selenium测试的运行。
$ mvn clean verify -P-selenium
标签:Web,Selenium,driver,测试,自动化,import,selenium
From: https://blog.51cto.com/basilguo/7423672