在本章中,我们将学习线程应用程序的测试。也将学习测试的重要性。
为什么要测试?
在我们深入讨论测试的重要性之前,需要知道什么是测试。 一般来说,测试是一种发现某件事情如何发挥作用的技术。 另一方面,特别是如果谈论计算机程序或软件,那么测试就是访问软件程序功能的技术。
在本节中,我们将讨论软件测试的重要性。 在软件开发中,在向客户端发布软件之前必须进行双重检查。 这就是为什么经验丰富的测试团队测试软件非常重要。 从以下几点来理解软件测试的重要性 -
1. 提高软件质量
当然,没有公司想要提供低质量的软件,也没有客户想要购买低质量的软件。 测试通过查找并修复其中的错误来提高软件的质量。
2. 客户满意度
任何企业最重要的部分是客户的满意度。 通过提供无错误和高质量的软件,公司可以实现客户满意度。
3. 减少新功能的影响
假设我们已经制作了10000行的软件系统,并且我们需要添加一个新功能,那么开发团队就会担心这个新功能对整个软件的影响。 在这里,测试也起着至关重要的作用,因为如果测试团队已经完成了一套很好的测试,那么它可以帮助我们避免任何潜在的灾难性休息。
4. 用户体验
任何业务中另一个最重要的部分是该产品用户的体验。 只有测试才能确保最终用户发现使用该产品简单易用。
5. 削减开支
测试可以通过在测试开发的测试阶段找到并修复错误而不是在交付后修复软件来降低软件的总成本。 如果在交付软件后出现重大缺陷,那么就费用和无形成本而言,例如客户不满意度,公司负面声誉等方面,它会增加其有形成本。
要测试什么?
总是建议对要测试的内容有适当的知识。 在本节中,我们将首先了解测试任何软件时测试人员的主要动机。 应该避免使用代码覆盖率,即测试套件在测试时碰到多少行代码。 这是因为,在测试时,只关注代码行数量并不会增加系统的实际价值。 可能存在一些错误,即使在部署之后,稍后也会反映出来。
考虑以下与测试内容相关的重要问题 -
- 需要关注测试代码的功能而不是代码覆盖。
- 需要首先测试代码中最重要的部分,然后转向代码中不太重要的部分。这肯定会节省时间。
- 测试仪必须有多种不同的测试,可以将软件推到极限。
测试并行软件程序的方法
由于利用多核架构的真实能力,并行软件系统正在取代顺序系统。 最近,从手机到洗衣机,从汽车到飞机等,所有的并发系统程序都在使用。需要更加小心地测试并发软件程序,因为如果为单线程应用程序添加了多个线程, 已经是一个错误,那么最终会遇到多个错误。
并发软件程序的测试技术主要集中在选择交错方面,这些交错方式暴露了潜在的有害模式,如竞态条件,死锁和原子性违规。 以下是测试并发软件程序的两种方法 -
系统的探索
这种方法旨在尽可能广泛地探索交织的空间。 这些方法可以采用强力技术,而其他方法则采用部分降阶技术或启发式技术来探索交织的空间。
属性驱动
属性驱动方法依赖于观察到并发错误更有可能发生在交错之下,这些交错揭示了诸如可疑内存访问模式之类的特定属性。 不同的财产驱动方法针对不同的故障,如竞态条件,死锁和违反原子性,这进一步取决于一个或其他特定属性。
测试策略
测试策略也被称为测试方法。 该策略定义了如何进行测试。 测试方法有两种技术 -
主动
尽早开始测试设计过程以便在创建构建之前查找并修复缺陷的方法。
反应
直到完成开发过程才开始测试的方法。
在对python程序应用任何测试策略或方法之前,我们必须对软件程序可能存在的错误类型有一个基本的想法。 错误如下 -
语法错误
在程序开发过程中,可能会出现很多小错误。 错误主要是由于输入错误。 例如,缺少冒号或关键字的拼写错误等。这些错误是由于程序语法中的错误,而不是逻辑中的错误。 因此,这些错误被称为语法错误。
语义错误
语义错误也被称为逻辑错误。 如果软件程序中存在逻辑或语义错误,则该语句将编译并正确运行,但由于逻辑不正确,它不会给出所需的输出。
单元测试
这是测试python程序最常用的测试策略之一。 该策略用于测试代码的单元或组件。 我们指单位或组件代表代码的类别或功能。 单元测试通过测试“小”单元来简化大型编程系统的测试。 在上述概念的帮助下,单元测试可以被定义为一种方法,其中对源代码的各个单元进行测试以确定它们是否返回期望的输出。
在接下来的章节中,我们将学习单元测试的不同Python模块。
unittest模块
单元测试的第一个模块是unittest
模块。 它受JUnit的启发,默认包含在Python3.6中。 它支持测试自动化,共享测试的设置和关闭代码,将测试集合到集合中,以及测试独立于报告框架。
以下是unittest
模块支持的一些重要概念
文本夹具
它用于设置测试,以便在测试结束后可以在开始测试和拆卸之前运行测试。 它可能涉及在开始测试之前创建临时数据库,目录等。
测试用例
测试用例检查所需的响应是否来自特定的一组输入。 unittest
模块包含一个名为TestCase
的基类,可用于创建新的测试用例。 它包括两个默认方法 -
setUp()
- 在锻炼之前设置测试夹具的钩子方法。 这在调用实现的测试方法之前调用。tearDown()
- 在类中运行所有测试之后解构类装置的钩子方法。
测试套件
它是测试套件,测试用例或两者的集合。
测试运行
它控制测试用例或套装的运行并向用户提供结果。 它可以使用GUI或简单的文本界面来提供结果。
以下Python程序使用unittest
模块来测试名为Fibonacci
的模块。 该计划有助于计算一个数字的斐波那契数列。 在这个例子中,我们创建了一个名为Fibo_test
类,通过使用不同的方法来定义测试用例。 这些方法从unittest.TestCase
继承。 我们使用两个默认方法 - setUp()
和tearDown()
。 也定义了testfibocal
方法。 测试名称必须以字母测试开始。 在最后的块中,unittest.main()
为测试脚本提供了一个命令行入口。
import unittest
def fibonacci(n):
a, b = 0, 1
for i in range(n):
a, b = b, a + b
return a
class Fibo_Test(unittest.TestCase):
def setUp(self):
print("This is run before our tests would be executed")
def tearDown(self):
print("This is run after the completion of execution of our tests")
def testfibocal(self):
self.assertEqual(fib(0), 0)
self.assertEqual(fib(1), 1)
self.assertEqual(fib(5), 5)
self.assertEqual(fib(10), 55)
self.assertEqual(fib(20), 6765)
if __name__ == "__main__":
unittest.main()
当从命令行运行时,上面的脚本产生一个看起来像这样的输出 -
This runs before our tests would be executed.
This runs after the completion of execution of our tests.
.
----------------------------------------------------------------------
Ran 1 test in 0.006s
OK
现在,为了更清楚一点,修改上面的代码,这有助于定义斐波那契模块。
以下面的代码块为例 -
def fibonacci(n):
a, b = 0, 1
for i in range(n):
a, b = b, a + b
return a
代码块的一些更改如下所示 -
def fibonacci(n):
a, b = 1, 1
for i in range(n):
a, b = b, a + b
return a
现在,使用更改后的代码运行脚本后,将得到以下输出 -
This runs before our tests would be executed.
This runs after the completion of execution of our tests.
F
======================================================================
FAIL: testCalculation (__main__.Fibo_Test)
----------------------------------------------------------------------
Traceback (most recent call last):
File "unitg.py", line 15, in testCalculation
self.assertEqual(fib(0), 0)
AssertionError: 1 != 0
----------------------------------------------------------------------
Ran 1 test in 0.007s
FAILED (failures = 1)
以上输出显示模块未能提供所需的输出。
Docktest模块
docktest
模块也有助于单元测试。 它也预装python。 它比单元测试模块更容易使用。 unittest模块更适合于复杂的测试。要使用doctest
模块,可以直接导入它。 相应函数的文档字符串必须具有交互式python会话及其输出。
如果代码中一切正常,那么docktest模块将不会有输出; 否则,它会提供输出。
示例
以下Python示例使用docktest
模块来测试名为Fibonacci
的模块,该模块有助于计算数字的斐波那契数列。
import doctest
def fibonacci(n):
"""
Calculates the Fibonacci number
>>> fibonacci(0)
0
>>> fibonacci(1)
1
>>> fibonacci(10)
55
>>> fibonacci(20)
6765
>>>
"""
a, b = 1, 1
for i in range(n):
a, b = b, a + b
return a
if __name__ == "__main__":
doctest.testmod()
可以看到名为fib
的相应函数的文档字符串具有交互式python会话和输出。 如果代码没有问题,那么doctest
模块将不会有输出。 但要了解它的工作原理,我们可以使用-v
选项运行它。
(base) D:\ProgramData>python dock_test.py -v
Trying:
fibonacci(0)
Expecting:
0
ok
Trying:
fibonacci(1)
Expecting:
1
ok
Trying:
fibonacci(10)
Expecting:
55
ok
Trying:
fibonacci(20)
Expecting:
6765
ok
1 items had no tests:
__main__
1 items passed all tests:
4 tests in __main__.fibonacci
4 tests in 2 items.
4 passed and 0 failed.
Test passed.
现在,我们将更改帮助定义斐波那契模块的代码,以下面的代码块为例 -
def fibonacci(n):
a, b = 0, 1
for i in range(n):
a, b = b, a + b
return a
以下代码块有助于更改 -
def fibonacci(n):
a, b = 1, 1
for i in range(n):
a, b = b, a + b
return a
在运行脚本后,即使没有-v
选项,使用更改后的代码,我们将得到如下所示的输出。
(base) D:\ProgramData>python dock_test.py
**********************************************************************
File "unitg.py", line 6, in __main__.fibonacci
Failed example:
fibonacci(0)
Expected:
0
Got:
1
**********************************************************************
File "unitg.py", line 10, in __main__.fibonacci
Failed example:
fibonacci(10)
Expected:
55
Got:
89
**********************************************************************
File "unitg.py", line 12, in __main__.fibonacci
Failed example:
fibonacci(20)
Expected:
6765
Got:
10946
**********************************************************************
1 items had failures:
3 of 4 in __main__.fibonacci
***Test Failed*** 3 failures.
我们可以在上面的输出中看到三个测试失败了。