热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Python基础教程:Pythonassert实现软件测试

Python对于测试非常看重,例如测试中最常见的操作——断言assert,其在Python中就是一个关键字而不是一个函数。而在C语言中,assert只是一个

Python 对于测试非常看重,例如测试中最常见的操作——断言 assert,其在 Python 中就是一个关键字而不是一个函数。而在 C 语言中,assert 只是一个普通的函数。从这点也可以看出,Python 将测试当作最基础的部分。

可以通过使用下面的代码来查看 Python 语言定义的关键字:

  >>> import keyword                                     # 引入模块keyword  >>> keyword.kwlist                                     # 得到所有的关键字  # 关键字列表  ['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await',  'break', 'class', 'continue', 'def', 'del', 'elif', 'else',  'except', 'finally', 'for', 'from', 'global', 'if', 'import',  'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass',  'raise', 'return', 'try', 'while', 'with', 'yield']

可以直接是使用 assert 在源代码中对其进行测试,常用的做法如图 1 所示。

Python assert实现软件测试
图 1 将测试代码和实现功能放入同一个文件

下面看一个简单的例子,假定自定义了一个模块 sampleAssert,其代码如下:

  def int_list_sort(input_list):          # 被测对象,完成对输入的整数列表排序      input_list.sort()                   # 完成排序  if __name__ == "__main__":                      # 判断条件,里面的内容是用来测试的      def test_normal_positive_input():                   # 定义一个测试用例          input_list = [3, 5, 9, 1, 8]          int_list_sort(input_list)          assert input_list == [1, 3, 5, 8, 9]          print("test_normal_positive_input: PASS")      test_normal_positive_input()                         # 执行测试用例

如果我们是 import(引入)该模块,case 是不会执行的,即第 3 行开始的块是不会执行的,所以包含在该块内的测试用例定义不会被看到,测试用例也不会被执行。

  $ python                                       # 启动解释器,Python 3  Python 3.7.3 (default, Mar 27 2019, 16:54:48)  [Clang 4.0.1 (tags/RELEASE_401/final)] :: Anaconda, Inc. on darwin  Type "help", "copyright", "credits" or "license" for more information.  >>> import sampleAssert                        # 引入我们刚才定义的模块  >>> sampleAssert.test_normal_positive_input()  # 测试函数是不可见的  Traceback (most recent call last):    File "", line 1, in   AttributeError: module 'sampleAssert' has no attribute 'test_normal_          positive_input'  >>> list_obj = [3, 1, 6, 100, 98, 9]  >>> sampleAssert.int_list_sort(list_obj)         # 被测对象是可见的  >>> list_obj  [1, 3, 6, 9, 98, 100]                            # 排序后的结果

如果是直接运行该脚本,则测试用例就会被触发。

  $ python sampleAssert.py  test_normal_positive_input: PASS

下面我们来实现一个冒泡排序法,其仅对整数列表有效。冒泡排序法是最简单的排序法,其通过交换相邻的元素来实现排序。下面以对包含 4 个元素 3、1、5、2 的列表进行排序为例来解释这个过程,如图 2 所示。

Python assert实现软件测试
图 2 冒泡排序

首先从尾部,也就是下部依次查找不符合排列要求的相邻两个数,第一次找到的是 5 和 2,交换它们,然后继续查找得到 3 和 1 这两个不符合要求的相邻数,交换它们。通过这一轮的交换,最小的数交换到了第一个元素。然后继续其他记录的排序,第二轮可以保证第二小的数排到第二个位置上。以此类推,最多经过 n-1 轮就可以完成所有数据的排序。

在这个例子中,经过了两轮就完成了所有数据的排序。

下面是完整的实现代码和相关测试代码:

  def bubble_sort(input_list):                    # 被测函数,冒泡排序      if type(input_list) is not type([]):        # 如果输入参数不符合要求          print("Invalid Input Type")          return None      for x in input_list:                                # 有元素不是整数,返回None          if type(x) != int:              return None      input_len = len(input_list)      print()      print("Origin:", input_list)      if input_len <= 1:                               # 没有元素或者仅包含一个元素          return input_list      for x in range(input_len-1):                # 如果顺序不对,和旁边的元素交换          swap_happens = False          for y in range(input_len-1, x, -1):              if input_list[y-1] > input_list[y]:                  input_list[y-1], input_list[y] = input_list[y], input_                          list[y-1]                  swap_happens = True          if swap_happens == False:               # 上一轮没有交换数据,已经排序完毕              break          print("Temp %d:" % x, input_list)      return input_list                                   # 返回排序完毕的列表  if __name__ == "__main__":                              # 如果是运行该脚本而不是引入该脚本      import random                                               # 测试代码开始      def test_empty_input():                             # 如果输入的列表为空          input = []          output = bubble_sort(input)          assert type(output) == type([])          assert len(output) == 0      def test_invalid_input():                   # 如果输入的不是列表          output = bubble_sort(1)          assert output is None      def test_one_element():                     # 如果列表仅包含一个元素          input = [1, ]          output = bubble_sort(input)        assert type(output) == type([])        assert len(output) == 1        assert output[0] == 1      def test_neg_one_element():         # 如果列表仅包含一个元素,而且不是整数        input = ["name", ]         output = bubble_sort(input)         assert output is None      def test_two_element():                     # 如果列表仅包含两个元素         input = [18, 8]          output = bubble_sort(input)          assert type(output) == type([])          assert len(output) == 2          assert output[0] == 8          assert output[1] == 18      def test_neg_two_element():         # 如果列表包含两个元素,但并不都是整数          input = [1, "name"]          output = bubble_sort(input)          assert output is None      def test_normal_pos():                              # 正常输入          input = [88, 1, 20, 8, 9, 21, 98, 76]          output = bubble_sort(input)          expected_output = [1, 8, 9, 20, 21, 76, 88, 98]          assert output == expected_output      def test_dup_elements():                    # 如果有重复的元素          input = [88, 1, 20, 8, 9, 21, 98, 8, 76]        # 两个8          print("input:", input)          output = bubble_sort(input)          print("outpout:", output)          expected_output = [1, 8, 8, 9, 20, 21, 76, 88, 98]          assert output == expected_output      def test_all_same():                                # 如果所有元素都相等          input = [8, 8, 8, 8, 8, 8]              # 所有的输入元素相同          output = bubble_sort(input)          expected_output = [8, 8, 8, 8, 8, 8]          assert output == expected_output      def random_test():                                  # 随机生成测试数据          # 生成随机的输入数据          expected_list_len = random.randint(10, 100)          input_list = []          for x in range(expected_list_len):              input_list.append(random.randint(-100, 100))          input_len = len(input_list)          org_input = input_list.copy()           # 备份一下元素数据          output = bubble_sort(input_list)          print("org_input", org_input)          #input_len = len(org_input)          assert len(output) == expected_list_len          for pos in range(input_len-1):              val = output[pos]              # 该数据在原始列表中存在              # 这样可以确保所有结果列表中的数据都是来自输入列表              assert val in org_input              # 而且其出现的次数和元素列表中出现的次数一致              # 这可保证输入列表中的数据不会丢失              assert output.count(val) == org_input.count(val)              # 保证有序,从小到大              assert val <= output[pos+1]      def test_random_data():                             # 随机输入测试          # 进行100轮随机输入的测试          for x in range(100):              random_test()      # 执行所有的测试      test_empty_input()      test_invalid_input()      test_one_element()      test_neg_one_element()      test_two_element()      test_neg_two_element()      test_normal_pos()      test_dup_elements()      test_all_same()      test_random_data()

可以发现测试代码的长度比被测代码的长度还要长,这是软件测试中,尤其是功能测试部分常见的现象。另外一个现象是对于针对特殊使用场景的测试用例数量比较大。多数情况下,问题不会隐藏在常用的使用场景,而多隐藏在这些不常见的使用场景中,所以针对这些特殊使用场景的测试用例的设计需要多下功夫。
以上就是Python基础教程:Python assert实现软件测试相关内容,想了解更多python基础教程关注(编程笔记)。


推荐阅读
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • PDO MySQL
    PDOMySQL如果文章有成千上万篇,该怎样保存?数据保存有多种方式,比如单机文件、单机数据库(SQLite)、网络数据库(MySQL、MariaDB)等等。根据项目来选择,做We ... [详细]
  • 本文介绍了在Windows系统上使用C语言命令行参数启动程序并传递参数的方法,包括接收参数程序的代码和bat文件的编写方法,同时给出了程序运行的结果。 ... [详细]
  • 本文介绍了使用Spark实现低配版高斯朴素贝叶斯模型的原因和原理。随着数据量的增大,单机上运行高斯朴素贝叶斯模型会变得很慢,因此考虑使用Spark来加速运行。然而,Spark的MLlib并没有实现高斯朴素贝叶斯模型,因此需要自己动手实现。文章还介绍了朴素贝叶斯的原理和公式,并对具有多个特征和类别的模型进行了讨论。最后,作者总结了实现低配版高斯朴素贝叶斯模型的步骤。 ... [详细]
  • 使用圣杯布局模式实现网站首页的内容布局
    本文介绍了使用圣杯布局模式实现网站首页的内容布局的方法,包括HTML部分代码和实例。同时还提供了公司新闻、最新产品、关于我们、联系我们等页面的布局示例。商品展示区包括了车里子和农家生态土鸡蛋等产品的价格信息。 ... [详细]
  • 本文介绍了GTK+中的GObject对象系统,该系统是基于GLib和C语言完成的面向对象的框架,提供了灵活、可扩展且易于映射到其他语言的特性。其中最重要的是GType,它是GLib运行时类型认证和管理系统的基础,通过注册和管理基本数据类型、用户定义对象和界面类型来实现对象的继承。文章详细解释了GObject系统中对象的三个部分:唯一的ID标识、类结构和实例结构。 ... [详细]
  • 使用C++编写程序实现增加或删除桌面的右键列表项
    本文介绍了使用C++编写程序实现增加或删除桌面的右键列表项的方法。首先通过操作注册表来实现增加或删除右键列表项的目的,然后使用管理注册表的函数来编写程序。文章详细介绍了使用的五种函数:RegCreateKey、RegSetValueEx、RegOpenKeyEx、RegDeleteKey和RegCloseKey,并给出了增加一项的函数写法。通过本文的方法,可以方便地自定义桌面的右键列表项。 ... [详细]
  • MySQL多表数据库操作方法及子查询详解
    本文详细介绍了MySQL数据库的多表操作方法,包括增删改和单表查询,同时还解释了子查询的概念和用法。文章通过示例和步骤说明了如何进行数据的插入、删除和更新操作,以及如何执行单表查询和使用聚合函数进行统计。对于需要对MySQL数据库进行操作的读者来说,本文是一个非常实用的参考资料。 ... [详细]
  • 判断编码是否可立即解码的程序及电话号码一致性判断程序
    本文介绍了两个编程题目,一个是判断编码是否可立即解码的程序,另一个是判断电话号码一致性的程序。对于第一个题目,给出一组二进制编码,判断是否存在一个编码是另一个编码的前缀,如果不存在则称为可立即解码的编码。对于第二个题目,给出一些电话号码,判断是否存在一个号码是另一个号码的前缀,如果不存在则说明这些号码是一致的。两个题目的解法类似,都使用了树的数据结构来实现。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
author-avatar
哆啦356
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有