酒店类的电影网站模板免费下载,什么是软件开发工具,鄂州一网,企业网站建设的研究开发方法及技术路线1.认识unittest在 Python 中有诸多单元测试框架#xff0c;如 doctest、unittest、pytest、nose 等#xff0c;Python 2.1 及其以后的版本已经将 unittest 作为一个标准模块放入 Python 开发包中。2.认识单元测试不用单元测试框架能写单元测试吗#xff1f;答案是肯定的。单…1.认识unittest在 Python 中有诸多单元测试框架如 doctest、unittest、pytest、nose 等Python 2.1 及其以后的版本已经将 unittest 作为一个标准模块放入 Python 开发包中。2.认识单元测试不用单元测试框架能写单元测试吗答案是肯定的。单元测试本质上就是通过一段代码去验证另外一段代码所以不用单元测试框架也可以写单元测试。下面就通过例子演示。创建一个被测试文件 calculator.py。# _*_ coding:utf-8 _*_name:zhangxingzai
date:2023/2/22
# 创建一个计算器类
class Calculator: 用于完成两个数的加、减、乘、除 def __init__(self, a, b):self.a int(a)self.b int(b)# 加法def add(self):return self.a self.b# 减法def sub(self):return self.a - self.b# 乘法def mul(self):return self.a * self.b# 除法def div(self):return self.a / self.b程序非常简单创建一个 Calculator 类通过__init__()方法接收两个参数并做 int 类型转换。创建 add()、sub()、mul()、div()方法分别进行加、减、乘、除运算。根据上面实现的功能创建 test_calculator.py 文件。# _*_ coding:utf-8 _*_name:zhangxingzai
date:2023/2/22
from calculator import Calculatordef test_add():c Calculator(3, 6)result c.add()assert result 9, 加法运算失败!def test_sub():c Calculator(7, 2)result c.sub()assert result 5, 减法运算失败!def test_mul():c Calculator(3, 3)result c.mul()assert result 10, 乘法运算失败!def test_div():c Calculator(6, 2)result c.div()assert result 3, 除法运算失败!if __name__ __main__:test_add()test_sub()test_mul()test_div()运行结果如下在测试代码中首先引入 calculator 文件中的 Calculator 类并对测试数据进行初始化。接下来调用该类下面的方法得到计算结果并断言结果是否正确。这样的测试存在着一些问题。首先我们需要自己定义断言失败的提示其次当一个测试函数运行失败后后面的测试函数将不再执行最后执行结果无法统计。当然我们可以通过编写更多的代码来解决这些问题但这就偏离了我们做单元测试的初衷。我们应该将重点放在测试本身而不是其他上面。引入单元测试框架可以很好地解决这些问题。下面通过 unittest 单元测试框架重新编写测试用例import unittest
from calculator import Calculatorclass TestCalculator(unittest.TestCase):def test_add(self):c Calculator(3, 6)result c.add()self.assertEqual(result, 9)def test_sub(self):c Calculator(7, 2)result c.sub()self.assertEqual(result, 5)def test_mul(self):c Calculator(3, 3)result c.mul()self.assertEqual(result, 10)def test_div(self):c Calculator(6, 2)result c.div()self.assertEqual(result, 3)if __name__ __main__:unittest.main()运行结果如下引入 unittest 模块。如果想用 unittest 编写测试用例那么一定要遵守它的“规则”。1创建一个测试类这里为 TestCalculator 类必须要继承 unittest 模块的 TestCase类。2创建一个测试方法该方法必须以“test”开头。接下来的测试步骤与前面测试代码相同。首先调用被测试类传入初始化数据。其次调用被测试方法得到计算结果。通过 unittest 提供的 assertEqual()方法来断言结果是否与预期结果相同。该方法由 TestCase 父类提供由于继承了该类所以可以通过self 调用。最后调用 unittest 的 main()来执行测试用例它会按照前面的两条规则查找测试用例并执行。3.unittest重要的概念 unittest 文档中有四个重要的概念Test Case、Test Suite、Test Runner 和 Test Fixture。只有理解了这几个概念才能理解单元测试的基本特征。1.Test CaseTest Case 是最小的测试单元用于检查特定输入集合的特定返回值。unittest 提供了TestCase 基类我们创建的测试类需要继承该基类它可以用来创建新的测试用例。2.Test Suite测试套件是测试用例、测试套件或两者的集合用于组装一组要运行的测试。unittest提供了 TestSuite 类来创建测试套件。3.Test RunnerTest Runner 是一个组件用于协调测试的执行并向用户提供结果。Test Runner 可以使用图形界面、文本界面或返回特殊值来展示执行测试的结果。unittest 提供了 TextTestRunner类运行测试用例为了生成 HTML 格式的测试报告后面会选择使用 HTMLTestRunner 运行类。4.Test FixtureTest Fixture 代表执行一个或多个测试所需的环境准备以及关联的清理动作。例如创建临时或代理数据库、目录或启动服务器进程。unittest 中提供了 setUp()/tearDown()、setUpClass()/tearDownClass()等方法来完成这些操作。在理解了上面几个概念之后我们对前面的测试用例做如下修改import unittest
from calculator import Calculatorclass TestCalculator(unittest.TestCase):# 测试用例前置动作def setUp(self):print(test start:)# 测试用例后置动作def tearDown(self):print(test end)def test_add(self):c Calculator(3, 5)result c.add()self.assertEqual(result, 8)def test_sub(self):c Calculator(7, 2)result c.sub()self.assertEqual(result, 5)def test_mul(self):c Calculator(3, 3)result c.mul()self.assertEqual(result, 10)def test_div(self):c Calculator(6, 2)result c.div()self.assertEqual(result, 3)if __name__ __main__:# 创建测试套件suit unittest.TestSuitesuit.addTest(TestCalculator(test_add))suit.addTest(TestCalculator(test_sub))suit.addTest(TestCalculator(test_mul))suit.addTest(TestCalculator(test_div))# 创建测试运行器runner unittest.TextTestRunner()runner.run(suit)首先创建一个测试类并继承 TestCase 类在该类下面创建一条以“test”开头的方法为测试用例。这个前面已有说明这里再次说明是为了强调它的重要性。其次在测试类中增加了 setUp()/tearDown()方法用于定义测试用例的前置和后置动作。因为在当前测试中暂时用不上所以这里定义了一些简单的打印。接下来是测试用例的执行这里做了很大的改动。首先抛弃了 unittest 提供的 main()方法而是调用 TestSuite 类下面的 addTest()来添加测试用例。因为一次只能添加一条用例所以需要指定测试类及测试方法。然后再调用 TextTestRunner 类下面的 run()运行测试套件这样做确实比直接使用 main()方法要麻烦得多但也并非没有优点。首先测试用例的执行顺序可以由测试套件的添加顺序控制而 main()方法只能按照测试类、方法的名称来执行测试用例。例如TestA 类比 TestB 类先执行test_add()用例比test_div()用例先执行。其次当一个测试文件中有很多测试用例时并不是每次都要执行所有的测试用例尤其是比较耗时的 UI 自动化测试。因而通过测试套件和测试运行器可以灵活地控制要执行的测试用例。执行结果如下test start:
test end
test start:
test end
test start:
test endRan 4 tests in 0.013s
FAILED (failures1)
10 ! 9
预期:9
实际:10
点击以查看差异Traceback (most recent call last):File C:\Users\Administrator\PycharmProjects\AutoFunction\test_calculator.py, line 28, in test_mulself.assertEqual(result, 10)
AssertionError: 9 ! 10test start:
test end从执行结果可以看到setUp/tearDown 作用于每条测试用例的开始之处与结束之处。4.断言方法在执行测试用例的过程中最终测试用例执行成功与否是通过测试得到的实际结果与预期结果进行比较得到的。unittest 框架的 TestCase 类提供的用于测试结果的断言方法如下表所示。断言方法的使用如下所示# _*_ coding:utf-8 _*_import unittestclass TestAssert(unittest.TestCase):def test_equal(self):self.assertEqual(2 2, 4)self.assertEqual(python, python)self.assertNotEqual(hello, python)def test_in(self):self.assertIn(hello, hello world)self.assertNotIn(hi, hello)def test_true(self):self.assertTrue(True)self.assertFalse(False)if __name__ __main__:unittest.main()运行上面的测试用例即可通过测试结果推断出这些断言方法是如何使用的。5.测试用例的组织与 discover 方法我们可以在一个测试文件中定义多个测试类只要它们遵循测试用例的“规则”main()方法就可以找到并执行它们。但是我们要测试的类或方法可能有很多。下面开发一个功能用于判断某年是否为闰年。创建 leap_year.py 文件。# _*_ coding:utf-8 _*_name:zhangxingzai
date:2023/2/23
class LeapYear:计算某年是否为闰年def __init__(self, year):self.year int(year)def answer(self):year self.yearif year % 100 0:if year % 400 0: # 整百年能被 400 整除的是闰年return {0}是闰年.format(year)else:return {0}不是闰年.format(year)else:if year % 4 0: # 非整百年能被 4 整除的是闰年return {0}是闰年.format(year)else:return {0}不是闰年.format(year)创建对应的测试文件 test_leap_year.py# _*_ coding:utf-8 _*_name:zhangxingzai
date:2023/2/23import unittest
from leap_year import LeapYearclass TestLeapYear(unittest.TestCase):def test_2000(self):ly LeapYear(2000)self.assertEqual(ly.answer(), 2000是闰年)def test_2004(self):ly LeapYear(2004)self.assertEqual(ly.answer(), 2004是闰年)def test_2017(self):ly LeapYear(2017)self.assertEqual(ly.answer(), 2017不是闰年)def test_2100(self):ly LeapYear(2100)self.assertEqual(ly.answer(), 2100不是闰年)if __name__ __main__:unittest.main()显然这里的判断闰年功能leap_year.py和计算器功能calculator.py并不相关它们的代码分别写在两个文件当中所以对应的测试用例最好分开分别为test_calculator.py和 test_leap_year.py。当前目录结构如下如何执行多个测试文件呢unittest中的TestLoader类提供的discover()方法可以从多个文件中查找测试用例。该类根据各种标准加载测试用例并将它们返回给测试套件。正常情况下不需要创建这个类的实例。unittest 提供了可以共享的 defaultTestLoader 类可以使用其子类或方法创建实例discover()方法就是其中之一。discover(start_dirpatterntest*.pytop_level_dirNone)找到指定目录及其子目录下的所有测试模块只有匹配的文件名才能被加载。如果启动的不是顶层目录那么顶层目录必须单独指定。start_dir 待测试的模块名或测试用例目录。patterntest*.py 测试用例文件名的匹配原则。此处匹配文件名以“test”开头的“.py”类型的文件星号“*”表示任意多个字符。top_level_dirNone测试模块的顶层目录如果没有顶层目录则默认为 None。现在通过 discover()方法重新实现 run_tests.py 文件的功能。import unittest
# 定义测试用例的目录为当前目录中的AutoFunction/目录
test_dir ./AutoFunction
suits unittest.defaultTestLoader.discover(test_dir, patterntest*.py)
if __name__ __main__:runner unittest.TextTestRunner()runner.run(suits)discover()方法会自动根据测试用例目录test_dir查找测试用例文件test*.py并将找到的测试用例添加到测试套件中因此可以直接通过 run()方法执行测试套件 suits。这种方式极大地简化了测试用例的查找我们需要做的就是按照文件的匹配规则创建测试文件即可。6.测试用例的执行顺序测试用例的执行顺序涉及多个层级多个测试目录 多个测试文件 多个测试类 多个测试方法测试用例。unittest 提供的 main()方法和 discover()方法是按照什么顺序查找测试用例的呢我们先运行一个例子再解释 unittest 的执行策略。# _*_ coding:utf-8 _*_name:zhangxingzai
date:date:2023/2/23
import unittestclass TestBdd(unittest.TestCase):def setUp(self):print(test TestBdd:)def test_ccc(self):print(test ccc)def test_aaa(self):print(test aaa)class TestAdd(unittest.TestCase):def setUp(self):print(test TestAdd:)def test_bbb(self):print(test bbb)if __name__ __main__:unittest.main()执行结果如下无论执行多少次结果都是一样的。通过上面的结果相信你已经找到 main()方法执行测试用例的规律了。因为unittest默认根据ASCII码的顺序加载测试用例的数字与字母的顺序为0~9A~Za~z所以 TestAdd 类会优先于 TestBdd 类被执行test_aaa()方法会优先于 test_ccc()方法被执行也就是说它并不是按照测试用例的创建顺序从上到下执行的。discover()方法和 main()方法的执行顺序是一样的。对于测试目录与测试文件来说上面的规律同样适用。test_aaa.py 文件会优先于 test_bbb.py 文件被执行。所以如果想让某个测试文件先执行可以在命名上加以控制。除命名外有没有其他办法控制测试用例的执行顺序呢答案是肯定的前面也有介绍我们可以声明测试套件 TestSuite 类通过 addTest()方法按照一定的顺序来加载测试用例。修改上面的例子如下# _*_ coding:utf-8 _*_name:zhangxingzai
date:date:2023/2/23
import unittestclass TestBdd(unittest.TestCase):def setUp(self):print(test TestBdd:)def test_ccc(self):print(test ccc)def test_aaa(self):print(test aaa)class TestAdd(unittest.TestCase):def setUp(self):print(test TestAdd:)def test_bbb(self):print(test bbb)if __name__ __main__:# 构造测试集suite unittest.TestSuite()suite.addTest(TestBdd(test_aaa))suite.addTest(TestAdd(test_bbb))suite.addTest(TestBdd(test_ccc))# 执行测试runner unittest.TextTestRunner()runner.run(suite)执行结果如下现在的执行顺序与 addTest()方法加载测试用例的顺序相同。不过当测试用例非常多时不推荐用这种方法创建测试套件原因前面也有说明最好的方法是通过命名控制执行顺序。如果测试用例在设计时不产生相互依赖那么测试用例的执行顺序就没那么重要了。7.跳过测试和预期失败在运行测试时有时需要直接跳过某些测试用例或者当测试用例符合某个条件时跳过测试又或者直接将测试用例设置为失败。unittest 提供了实现这些需求的装饰器。无条件地跳过装饰的测试需要说明跳过测试的原因unittest.skip(reason) 如果条件为真则跳过装饰的测试unittest.skipIf(condition, reason)当条件为真时执行装饰的测试unittest.skipUnless(condition, reason)不管执行结果是否失败都将测试标记为失败unittest.expectedFailure()举例如下import unittestclass MyTest(unittest.TestCase):unittest.skip(直接跳过测试)def test_skip(self):print(test aaa)unittest.skipIf(3 2, 当条件为真时跳过测试)def test_skip_if(self):print(test bbb)unittest.skipUnless(3 2, 当条件为真时执行测试)def test_skip_unless(self):print(test ccc)unittest.expectedFailuredef test_expected_failure(self):self.assertEqual(2, 3)if __name__ __main__:unittest.main()执行结果如下Skipped: 直接跳过测试
Skipped: 当条件为真时跳过测试
test ccc
Ran 4 tests in 0.010s
OK (skipped2, expected failures1)上面的例子创建了四条测试用例。第一条测试用例通过unittest.skip()装饰直接跳过测试。第二条测试用例通过unittest.skipIf()装饰当条件为真时跳过测试32 条件为真True所以跳过测试。第三条测试用例通过unittest.skipUnless()装饰当条件为真时执行测试32 条件为真True执行测试。第四条测试用例通过unittest.expectedFailure 装饰不管执行结果是否失败都将测试标记为失败但不会抛出失败信息。8.Fixtuer测试夹具我们可以把 Fixture 看作夹心饼干外层的两片饼干这两片饼干就是 setUp/tearDown中间的奶油就是测试用例。除此之外unittest 还提供了更大范围的 Fixture如测试类和模块的 Fixture。# _*_ coding:utf-8 _*_name:zhangxingzaiimport unittestdef setUpModule():print(test module start )def tearDownModule():print(test module end )class MyTest(unittest.TestCase):classmethoddef setUpClass(cls):print(test class start )classmethoddef tearDownClass(cls):print(test class end )def setUp(self):print(test case start --)def tearDown(self):print(test case end --)def test_case1(self):print(test case1)def test_case2(self):print(test case2)if __name__ __main__:unittest.main()执行结果如下test module start
test class start
test case start --
test case1
test case end --
test case start --
test case2
test case end --
test class end
test module end
Ran 2 tests in 0.005s
OKsetUpModule/tearDownModule在整个模块的开始与结束时被执行。setUpClass/tearDownClass在测试类的开始与结束时被执行。setUp/tearDown在测试用例的开始与结束时被执行。需要注意的是setUpClass/tearDownClass 为类方法需要通过classmethod 进行装饰。另外方法的参数为 cls。其实cls 与 self 并没有什么本质区别都只表示方法的第一个参数。