📅  最后修改于: 2020-11-08 08:46:40             🧑  作者: Mango
在本章中,我们将学习线程应用程序的测试。我们还将学习测试的重要性。
在深入讨论测试重要性之前,我们需要了解什么是测试。一般而言,测试是一种找出某件产品工作状况的技术。另一方面,特别是如果我们谈论计算机程序或软件,则测试是访问软件程序功能的技术。
在本节中,我们将讨论软件测试的重要性。在软件开发中,在将软件发布给客户端之前,必须进行仔细检查。因此,由经验丰富的测试团队测试软件非常重要。考虑以下几点,以了解软件测试的重要性-
当然,没有公司希望提供低质量的软件,也没有客户希望购买低质量的软件。测试通过发现并修复其中的错误来提高软件的质量。
任何业务中最重要的部分是客户的满意度。通过提供无缺陷且高质量的软件,公司可以实现客户满意度。
假设我们已经建立了一个10000行的软件系统,并且需要添加一个新功能,那么开发团队将担心此新功能对整个软件的影响。在这里,测试也起着至关重要的作用,因为如果测试团队进行了一系列出色的测试,那么它可以使我们免于遭受任何潜在的灾难性破坏。
任何业务的另一个最重要的部分是该产品用户的体验。只有进行测试才能确保最终用户发现该产品简单易用。
通过在开发的测试阶段查找并修复错误,而不是在交付后进行修复,测试可以降低软件的总成本。如果软件交付后出现重大错误,则将增加其有形成本(如费用),无形成本(如客户不满意,公司的负面声誉等)。
始终建议您对要测试的内容具有适当的了解。在本节中,我们将首先了解测试任何软件时测试人员的主要动机。代码覆盖率,即在测试期间应避免测试套件命中多少行代码。这是因为在测试时,仅关注代码行数不会对我们的系统增加任何实际价值。可能仍然存在一些错误,即使在部署之后,这些错误也会在稍后的某个阶段反映出来。
考虑以下与要测试的内容有关的要点-
我们需要集中精力测试代码的功能,而不是代码覆盖率。
我们需要先测试代码中最重要的部分,然后再测试代码中次重要的部分。肯定会节省时间。
测试人员必须进行多种不同的测试,才能将软件推向极限。
由于能够利用多核体系结构的真正功能,并发软件系统正在取代顺序系统。近年来,并发系统程序被用于从手机到洗衣机,从汽车到飞机等的所有事物。我们需要更加谨慎地测试并发软件程序,因为如果我们在具有以下功能的单线程应用程序中添加了多个线程,已经是一个错误,那么我们最终会遇到多个错误。
并发软件程序的测试技术广泛地集中在选择交织上,这些交织暴露出潜在的有害模式,例如竞争条件,死锁和违反原子性。以下是测试并发软件程序的两种方法-
该方法旨在尽可能广泛地探索交错的空间。这样的方法可以采用蛮力技术,而其他方法则可以采用偏序降阶技术或启发式技术来探索交错的空间。
属性驱动的方法依赖于这样的观察,即在暴露特定属性(例如可疑内存访问模式)的交错情况下,并发错误更有可能发生。不同的属性驱动方法针对不同的故障,例如竞态条件,死锁和违反原子性,这进一步取决于一个或其他特定属性。
测试策略也称为测试方法。该策略定义了如何进行测试。测试方法有两种技术-
一种方法,在这种方法中,应尽早启动测试设计过程,以便在创建构建之前发现并修复缺陷。
一种测试,直到开发过程完成才开始测试。
在对Python程序应用任何测试策略或方法之前,我们必须对软件程序可能存在的错误类型有一个基本的了解。错误如下-
在程序开发过程中,可能会出现许多小错误。该错误主要是由于键入错误引起的。例如,冒号丢失或关键字的拼写错误等。此类错误是由于程序语法错误而不是逻辑错误引起的。因此,这些错误称为语法错误。
语义错误也称为逻辑错误。如果软件程序中存在逻辑或语义错误,则该语句将编译并正确运行,但由于逻辑不正确,因此不会提供所需的输出。
这是测试Python程序最常用的测试策略之一。此策略用于测试代码的单元或组件。所谓单元或组件,是指代码的类或功能。单元测试通过测试“小型”单元,简化了大型编程系统的测试。借助以上概念,可以将单元测试定义为一种方法,其中对源代码的各个单元进行测试以确定它们是否返回所需的输出。
在接下来的部分中,我们将学习用于单元测试的不同Python模块。
单元测试的第一个模块是unittest模块。它受到JUnit的启发,默认情况下包含在Python3.6中。它支持测试自动化,共享测试的设置和关闭代码,将测试聚合到集合中以及测试与报告框架的独立性。
以下是unittest模块支持的一些重要概念
它用于设置测试,以便可以在开始测试之前运行它,并在测试完成后将其拆除。它可能涉及在开始测试之前创建所需的临时数据库,目录等。
测试用例检查所需的响应是否来自特定的输入集。 unittest模块包括一个名为TestCase的基类,可用于创建新的测试用例。默认情况下,它包括两个方法-
setUp() -一种在执行测试夹具之前设置测试夹具的挂钩方法。在调用实现的测试方法之前将调用此方法。
tearDown( -一个钩子方法,用于在运行类中的所有测试后解构类夹具。
它是测试套件和/或测试用例的集合。
它控制测试用例或套装的运行,并将结果提供给用户。它可以使用GUI或简单的文本界面来提供结果。
例
以下Python程序使用unittest模块测试名为Fibonacci的模块。该程序有助于计算数字的斐波那契数列。在此示例中,我们创建了一个名为Fibo_test的类,以使用不同的方法定义测试用例。这些方法是从unittest.TestCase继承的。默认情况下,我们使用两种方法– setUp()和tearDown()。我们还定义了睾丸方法。测试的名称必须以字母test开头。在最后一个块中,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
现在,为了更清楚一点,我们正在更改有助于定义Fibonacci模块的代码。
考虑以下代码块作为示例-
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模块还有助于进行单元测试。它还预包装了Python。它比unittest模块更容易使用。 unittest模块更适合复杂的测试。为了使用doctest模块,我们需要导入它。相应函数的文档字符串必须具有交互式Python会话及其输出。
如果我们代码中的所有内容都没问题,那么docktest模块将不会输出任何信息;否则,它将提供输出。
以下Python示例使用docktest模块测试名为Fibonacci的模块,该模块有助于计算数字的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.
现在,我们将更改有助于定义Fibonacci模块的代码
考虑以下代码块作为示例-
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.
我们可以在上面的输出中看到三个测试都失败了。