前言
本节将介绍如何结合 unittest 进行自动化测试,以及使用 Page Object 设计模式提高测试代码的可维护性。
知识点
结合 unittest 进行测试
Unittest 是 Python 自带的单元测试框架,它可以帮助我们更好地组织测试代码,提高测试的可维护性。
Unittest 主要可以用于组织和执行测试用例,并提供了丰富的断言方法,可以用于判断测试结果是否符合预期。
Unittest 简介
Unittest 是 Python 的官方单元测试框架,主要由以下几个部分组成:
TestCase(测试用例): 定义了一个测试用例,包括测试环境的搭建(setUp)、测试用例的执行(test_*方法)、以及测试环境的还原(tearDown)。
TestSuite(测试套件): 将多个测试用例组织在一起,方便进行批量执行。
TestRunner(测试运行器): 控制测试用例的执行流程,输出测试结果。
TestFixture(测试夹具): 提供测试用例执行所需的一些资源或环境。
Unittest 的基本结构
一个基本的 Unittest 测试用例结构如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import unittest
class MyTestCase(unittest.TestCase): def setUp(self): pass
def tearDown(self): pass
def test_example(self): self.assertEqual(1 + 1, 2)
if __name__ == '__main__': unittest.main()
|
在这个例子中,MyTestCase
继承自 unittest.TestCase
,并包含了 setUp
、tearDown
和一个测试方法 test_example
。
Unittest 示例
以下是一个简单的 Unittest 测试用例示例,测试一个加法操作:
1 2 3 4 5 6 7 8 9
| import unittest
class TestMathOperations(unittest.TestCase): def test_addition(self): result = 1 + 1 self.assertEqual(result, 2, "加法运算错误")
if __name__ == '__main__': unittest.main()
|
这个测试用例包含了一个测试方法 test_addition
,用于测试加法运算的正确性。
在这个示例中,使用了 self.assertEqual()
断言方法,用于判断 result
是否等于期望值 2
。如果不相等,会输出断言错误信息 “加法运算错误”。
通过结合 Unittest 进行自动化测试,可以更好地组织测试代码,提高测试的可维护性。
测试用例的编写
通过上面简单的示例,我们已经了解了 Unittest 的基本结构,接下来我们将结合实际的测试场景,编写一个完整的 Selenium 测试用例。
步骤
- 导入必要的模块:
1 2 3
| import unittest from selenium import webdriver from selenium.webdriver.common.by import By
|
- 创建测试类,并在
setUp
方法中进行初始化操作,如启动浏览器和打开测试网页:
1 2 3 4
| class TestLoginPage(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome() self.driver.get("https://selenium-app.im0o.top/login-example")
|
- 编写测试方法,验证登录功能。这里以输入用户名和密码,点击登录按钮为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| def test_login_success(self): username_input = self.driver.find_element(By.ID, 'username') password_input = self.driver.find_element(By.ID, 'password') username_input.send_keys('admin') password_input.send_keys('rootadmin')
login_button = self.driver.find_element(By.XPATH, '//*[@id="app"]/div/form/input[3]') login_button.click()
welcome_message = self.driver.find_element(By.ID, 'login-example-result') self.assertEqual(welcome_message.text, '登录成功', "登录失败")
|
- 在
tearDown
方法中进行清理操作,关闭浏览器:
1 2 3
| def tearDown(self): self.driver.quit()
|
- 运行测试用例:
1 2
| if __name__ == '__main__': unittest.main()
|
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import unittest from selenium import webdriver from selenium.webdriver.common.by import By
class TestLoginPage(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome() self.driver.get("https://selenium-app.im0o.top/login-example")
def test_login_success(self): username_input = self.driver.find_element(By.ID, 'username') password_input = self.driver.find_element(By.ID, 'password') username_input.send_keys('admin') password_input.send_keys('rootadmin')
login_button = self.driver.find_element(By.XPATH, '//*[@id="app"]/div/form/input[3]') login_button.click()
welcome_message = self.driver.find_element(By.ID, 'login-example-result') self.assertEqual(welcome_message.text, '登录成功', "登录失败") def tearDown(self): self.driver.quit()
if __name__ == '__main__': unittest.main()
|
通过以上步骤,我们完成了一个简单的 Selenium 测试用例,用于验证登录页面的基本功能。
运行结果
通过 Pycharm 的测试运行器,可以看到测试用例的执行结果。
Page Object 设计模式
Page Object 设计模式是一种常用的测试设计模式,它将页面的元素和操作封装成一个对象,方便测试用例的编写和维护。
Page Object 设计模式的优势
提高测试用例的可维护性: 将页面元素和操作封装成一个对象,方便测试用例的编写和维护。
提高测试用例的复用性: 一个页面对应一个 Page Object 对象,可以在多个测试用例中复用。
提高测试用例的可读性: 通过 Page Object 对象的方法名,可以直观地了解测试用例的执行逻辑。
Page Object 设计模式的实现
Page Object 设计模式的实现,主要包括以下几个步骤:
创建一个 Page Object 对象,用于封装页面元素和操作。
在测试用例中,实例化 Page Object 对象,并调用其中的方法。
实例:使用 Page Object 设计模式编写测试用例
在配套网页——实例:使用 Selenium 模拟用户登录 中,我们已经实现了一个简单的登录页面,现在我们将使用 Page Object 设计模式,编写一个测试用例,验证登录功能。
登录页面
登录页面包含以下元素:
元素 |
ID |
class |
name |
备注 |
用户名输入框 |
username |
- |
username |
- |
密码输入框 |
password |
- |
password |
- |
登录按钮 |
- |
- |
- |
使用 Xpath 或定位 input[type=”submit”] |
登录成功提示 |
login-example-result |
login-example-result |
login-example-result |
- |
Page Object 设计模式
Page Object 设计模式将页面的元素和操作封装在一个类中,以提高测试代码的可维护性。我们将创建一个 LoginPage
类,用于表示登录页面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait
class LoginPage: def __init__(self, driver): self.driver = driver self.url = "https://selenium-app.im0o.top/login-example" self.username_input = (By.ID, 'username') self.password_input = (By.ID, 'password') self.login_button = (By.XPATH, '//*[@id="app"]/div/form/input[3]') self.result = (By.ID, 'login-example-result') self.driver.implicitly_wait(10)
def open(self): self.driver.get(self.url)
def input_username(self, username): self.driver.find_element(*self.username_input).send_keys(username)
def input_password(self, password): self.driver.find_element(*self.password_input).send_keys(password)
def click_login_button(self): self.driver.find_element(*self.login_button).click()
def get_result(self): wait = WebDriverWait(self.driver, 10) wait.until(lambda driver: self.driver.find_element(*self.result)) return self.driver.find_element(*self.result).text
|
测试用例
使用 Page Object 设计模式编写的测试用例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import unittest from selenium import webdriver from login_page import LoginPage
class TestLoginPage(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome() self.login_page = LoginPage(self.driver) self.login_page.open()
def test_login_success(self): self.login_page.input_username('admin') self.login_page.input_password('rootadmin') self.login_page.click_login_button() result = self.login_page.get_result() self.assertEqual(result, '登录成功', "登录失败")
def tearDown(self): self.driver.quit()
if __name__ == '__main__': unittest.main()
|
通过 Page Object 设计模式,我们将页面元素和操作封装在 LoginPage
类中,测试用例更加清晰和可维护。
运行结果
添加测试用例
Page Object 的优势在于,可以在多个测试用例中复用。我们可以在 TestLoginPage
类中,添加多个测试用例,验证登录页面的其他功能。
1 2 3 4 5 6
| def test_login_failed(self): self.login_page.input_username('admin') self.login_page.input_password('123456') self.login_page.click_login_button() result = self.login_page.get_result() self.assertEqual(result, '用户名或密码错误', "登录成功")
|
At last
头图/封面素材来源:Photo by Hal Gatewood on Unsplash