使用 PyUnit 测试 Selenium Python 测试套件
众所周知,Selenium 是一款用于跨平台浏览器自动化测试的开源测试套件。由于其流行性和易用性,许多与不同编程语言兼容的测试框架应运而生,从而扩展了Selenium对多种编程语言的跨浏览器测试支持。今天,我们将学习 Selenium Python 教程,并使用 PyUnit 框架和 Selenium 运行我们的第一个自动化脚本。
PyUnit 是一个单元测试框架,它源自 JUnit,旨在使 Selenium 与 Python 语言兼容。PyUnit 是一个非常流行的测试框架,用于执行“单元测试”——一种验证模块中特定功能的方法。PyUnit 作为 Python 专用单元测试框架的流行,是 Python 从 2.5 版本开始将其作为官方模块收录的主要原因之一。Python 的 UnitTest 库(简称 unittest)被广泛用于执行Selenium Python 测试。在本 Selenium Python 教程中,我们将使用 unittest 库。
Python 单元测试 [PyUnit] 框架的构建模块
让我们从了解 PyUnit 框架的基本组成部分开始 Selenium Python 教程。unittest 框架包含以下核心模块,这些模块对于测试用例的开发和执行至关重要:
-
测试加载器:测试加载器 Python 类用于加载测试用例和测试套件。它也被称为“测试夹具”。测试用例和测试套件可以在本地创建,也可以从外部文件/数据库加载。测试成功执行后,测试加载器会释放测试套件对象,该对象可以在测试用例执行过程中继续使用。
-
测试运行器:负责通过可运行的界面向最终用户显示已执行测试的输出结果。输出结果可以以多种方式呈现,例如以图形用户界面 (GUI) 的形式显示标准代码,或以文本形式显示。
-
测试套件:测试套件是一组测试用例,这些用例根据被测功能进行逻辑分组。测试套件用于使测试代码更模块化、更易于维护。
-
测试用例:测试用例包含测试代码的实际实现。如果某些功能尚未完成,开发人员可以使用桩代码(即虚拟源代码)来对源代码进行单元测试。
-
测试报告:测试报告主要用于整理测试用例的执行结果,例如测试用例的执行结果是通过还是失败。它还详细记录执行时间、执行摘要等信息。测试报告维护得越好,就越容易从中提取有用的信息。
PyUnit/unittest 概述
PyUnit 也被称为 unittest,其工作方式与 xUnit 类似。xUnit 是一个非常流行的单元测试框架,其结构和功能源自Smalltalk 的 SUnit。因此,有 xUnit 或其他流行单元测试框架使用经验的开发人员会发现 unittest 更容易理解。
使用 unittest 模块编写的测试用例/测试套件遵循通用格式。
-
定义一个继承自 unittest.TestCase() 的类。我们将在后续章节中更详细地讨论 TestCase()。
-
定义命名规则为 test_name 的测试用例
-
通过 unittest.main() 执行测试用例/测试套件,该函数通常位于文件底部,即在实现测试用例执行所需的类之后。
我们将在后续章节中详细介绍 unittest 包中的重要类。
你知道吗?LT Debug Chrome 扩展程序让调试任何网页变得轻而易举。
setUp() 和 tearDown() — 初始化和反初始化
`setUp()` 方法是测试用例的入口点,它不接受任何参数。由于它是入口点,一些重要的初始化步骤会在 `setUp()` 方法的实现中执行。以下是一些可以包含在 `setUp()` 方法中的初始化相关步骤。
-
加载测试数据。
-
使用 WebDriver 接口创建浏览器实例,例如 Firefox。
-
打开文件进行 I/O(输入/输出)操作,无论是读取测试数据还是追加测试执行结果。
下面是一个通过 setUp() 和 tearDown() 方法执行的初始化和清理活动的示例。
import unittest
#Import other modules that are required for testing
class SearchText(unittest.TestCase):
def setUp(self):
#create a new FireFox session
self.driver = webdriver.FireFox()
.................................
.................................
self.driver.get("[https://www.lambdatest.com](https://www.lambdatest.com)")
def tearDown(self):
.................................
.................................
self.driver.quit()
在上面的示例中,使用 WebDriver API 创建了一个 Firefox 浏览器实例(第 7 行)。创建成功后,Firefox 浏览器会打开主页https://www.lambdatest.com。然后执行单元测试所需的所有必要操作。单元测试完成后,使用 tearDown() API 执行清理工作(第 12 行)。简而言之,setUp() 和 tearDown() 在每个测试方法之前和之后都会执行。
现在你已经了解了用 Python 编写的单元测试用例的初始化和反初始化的基础知识,让我们来看看本 Selenium Python 教程中的一些重要类。
PyUnit — 类和函数
class unittest.TestCase(methodName='TestName')
在本 Selenium Python 教程的后续章节中,我们将详细介绍 unittest 包中的重要类。具体的测试用例在子类中实现。在许多情况下,无需更改 methodName,也无需实现 runTest() 方法。我们已经讨论了重要的初始化方法 setUp() 和 tearDown(),现在我们将了解其他方法。
-
设置类()
-
类方法会在调用任何单独的测试之前被调用。`@classmethod` 是用于标识 `setUpClass()` 方法的标识符。`setUpClass()` 方法只有一个参数,即类名。
-
撕毁类()
-
此方法在类中的所有测试执行完毕后调用。与 setUpClass() 类似,tearDownClass() 也只接受一个参数,即类名。“类名”必须与 setUpClass() 中使用的名称一致,否则可能会导致错误。以下示例实现了 setUpClass() 和 tearDownClass() 的用法:
导入 unittest
class Example(unittest.TestCase):
@classmethod
def setUpClass(class_name):
print("setUpClass 已执行")def setUp(self):
print("setUp 已执行")def test_1(self):
print("test-1 已执行")def test_2(self):
print("test-2 已执行")def tearDown(self):
print("tearDown 已执行")@classmethod
def tearDownClass(class_name):
print("tearDownClass 已执行")
可能会出现一个问题——`setUp()` 和 `setUpClass()`(或者 `tearDown()` 和 `tearDownClass()`)之间有什么根本区别?`setUp()`(及其反初始化对应函数 `tearDown()`)会在每个测试方法之前加载并执行,而 `setUpClass()`(及其反初始化对应函数 `tearDownClass()`)则只对整个类执行一次。让我们通过一个简单的例子来理解它们的区别。
如下面的示例 [SetupClass-Python.py] 所示,根据执行的测试用例 [test_1 或 test_2],setUpClass 函数首先执行一次,然后执行相应的测试用例。测试用例执行完毕后,tearDownClass() 函数中的代码才会执行。
要执行代码,请按 CTRL+F9。如下截图所示,本 Selenium Python 教程中的两个测试用例均按以下执行顺序执行:
-
setUpClass() 下的实现已执行
-
执行 test_1(对 test_1 调用 setUp 和 tearDown,即在执行 test_1 后进行初始化和清理)。
-
测试 2 执行完毕(测试 2 执行完毕后会调用 setUp 和 tearDown 函数,即进行初始化和清理)。
-
tearDownClass() 下的实现已执行
如前所述,setUpClass() 和 tearDownClass() 只执行一次,而 setUp() 和 tearDown() 则针对每个测试方法执行一次。
- 运行(结果=None):
TestResult 对象作为参数传递给 run() 方法。该参数是可选的,如果未向方法提供对象,则会创建一个临时对象来存储结果。结果将传递给 run() 方法的调用者。我们将在后续章节中详细讨论 TestResult 对象。
您知道吗? LT Debug Chrome 扩展程序上的内容安全策略功能可以帮助您在您选择的任何网站或网页上生成内容安全策略标头。
class unittest.TestSuite(tests=())
TestSuite 类是各个测试用例和测试套件的集合。开发人员和测试人员无需迭代地执行测试用例,即可使用此类,因为它能简化代码维护。
与 TestCase() 类不同,TestSuite() 类不包含任何测试代码的实现,因为它用于按逻辑/功能对测试用例进行分组。下面列出了一些可以与 TestSuite() 类一起使用的方法。
-
addTest(test) : 用于添加测试用例或测试套件
-
addTests(tests) : 如果您计划遍历测试用例或测试套件,则可以使用 addTests()。
-
debug():此方法主要用于调试目的,因为它不返回执行结果。
-
run(result):如果您计划执行与测试套件关联的测试用例,可以使用 run(result)。result 对象存储执行结果。
class unittest.TestResult
TestResult 类用于收集有关已通过、失败和已跳过的测试用例数量的信息。如前所述,TestCase 和 TestSuite 类用于记录测试用例/测试套件的执行结果。TestResult 的一些重要属性包括 failures、errors、skipped、expectedFailures 和 unexpectedSuccesses。
这里有一篇关于2022 年 30 款顶级自动化测试工具的文章!
PyUnit 测试框架中的断言
无论使用何种编程语言编写测试代码,断言在测试中都非常流行。断言本质上是一个布尔表达式(表示“真/假”),在测试代码中遇到错误/问题之前,其值始终为“真” 。断言分为三种类型:等价性检查、比较以及在出现异常时执行操作。
接下来,在本 Selenium Python 教程中,我们将了解 PyUnit 框架的一些重要断言。
掌握了 PyUnit/unittest 的基础知识后,让我们来看一段示例代码,深入探讨一下目前为止讨论过的各个方面。
'''This sample program demonstrates the PyUnit/unittest framework'''
# Inclusion of the PyUnit Test Framework
import unittest
def addition(x,y,z=0):
# Add the three parameters which are passed to the addition function
return x+y+z
# This is where the test case is implemented
class AddTest(unittest.TestCase):
def setUp(self):
# initialization code for the testcase/testsuite can be added here
pass
# These are tests that should be performed once the basic premise is set
# Unit Tests start with test_
# The addition method which was implemented earlier will be used here
def test_addtion(self):
self.assertEqual(addition(10,11,12), 33)
# x=11, y=12, z=44 if (x+y)=z, the test would raise an assert since
# the test is for assertNotEqual operation
self.assertNotEqual(addition(11,12), 44)
def test_negative_values(self):
self.assertEqual(addition(-9,25), 16)
self.assertNotEqual(addition(-9,25), 17)
def tearDown(self):
# Deinit and cleanup should be done here
pass
if __name__=='__main__':
unittest.main()
上述代码包含两个测试用例——test_addition() 和 test_negative_values()。其中创建了一个名为 addition() 的方法(第 6 行至第 8 行),用于对传递给该方法的三个参数进行加法运算。测试用例中使用了 assertNotEqual 和 assertEqual 断言。如果断言中的条件为 TRUE,则相应的测试用例通过。执行上述代码后,最终测试结果为 PASS,因为 assertNotEqual 和 assertEqual 中指定的条件均已满足。例如,在 test_addition() 测试用例中,如果 x=10、y=11 和 z=12 的和不等于 33,则会调用 assert,因为它测试的是“相等”运算。以下是代码在命令行中编译和测试后的输出截图(文件 — Python-unittest-output1.png)。
为了调用断言,我们对 test_negative_values() 测试用例做了一些小修改。以下是修改后的源代码[修改部分已用注释标记]。
'''This sample program demonstrates the PyUnit/unittest framework'''
# Inclusion of the PyUnit Test Framework
import unittest
def addition(x,y,z=0):
# Add the three parameters which are passed to the addition function
return x+y+z
# This is where the test case is implemented
class AddTest(unittest.TestCase):
def setUp(self):
# initialization code for the testcase/testsuite can be added here
pass
# These are tests that should be performed once the basic premise is set
# Unit Tests start with test_
# The addition method which was implemented earlier will be used here
def test_addtion(self):
self.assertEqual(addition(10,11,12), 33)
# x=11, y=12, z=44 if (x+y)=z, the test would raise an assert since
# the test is for assertNotEqual operation
self.assertNotEqual(addition(11,12), 44)
def test_negative_values(self):
self.assertNotEqual(addition(-9,25), 16) #Changed Values#
def tearDown(self):
# Deinit and cleanup should be done here
pass
if __name__=='__main__':
unittest.main()
如第 27 行所示,如果 (x+y)!=z,则会发出断言。在我们的示例中,x=-9,y=25,z=16。由于测试条件不成立,因此会发出断言。您可以在下面的 Selenium Python 教程中看到输出的快照。
概括:
这篇 Selenium Python 教程帮助我们理解了 PyUnit 的一些重要方面。特别是如何使用这个高效的单元测试框架来自动化跨浏览器测试代码,以及如何在测试代码时有效地使用“断言”。PyUnit 还可以用于执行模块级测试,因为它也提供了执行极端测试用例的灵活性。在本文中,我们使用 Notepad++ 和“命令行 Python”来编写和执行 PyUnit 代码。作为开发人员,您应该使用自己喜欢且用起来最顺手的 IDE 和编程环境。虽然 PyUnit 最初是为 Python 的“C”语言编写的,但现在也可以使用 Jython 框架为 Java 等语言编写 PyUnit 测试。本文篇幅有限,无法详细介绍 Jython。您可以在这里找到 PyUnit/unittest 的官方文档。
文章来源:https://dev.to/lambdatest/using-pyunit-for-testing-a-selenium-python-test-suite-1kp9



