Python进阶(2) | 排序算法的单元测试
文章目录
1. 目的
在数组元素排序这个任务上,使用 Python 编写单元测试, 并且进一步熟悉 VSCode 里的 Testing 界面的使用。
2. 任务来源
在 Python testing in Visual Studio Code 文档中提到, 可以查看 py-sorting 的代码, 它是一个包含了完整的代码测试代码的这里。
3. py-sorting 介绍
git clone https://github.com/gwtw/py-sorting
A collection of sorting algorithms written in Python.
py-sorting 仓库实现了多种排序算法,每一种排序算法的实现,都是一个单元。
先来看 sort 目录:
- bubble_sort_optimised.py : 优化过的冒泡排序
- bubble_sort.py : 冒泡排序
- bucket_sort.py : 桶排序
- cocktail_sort.py : 鸡尾酒排序
- comb_sort.py : 不知道。
- counting_sort.py : 计数排序?
- gnome_sort.py: gnome 排序?
- heapsort.py :堆排序
- insertion_sort.py : 插入排序
- merge_sort_bottom_up.py : 自底向上的归并排序
- merge_sort.py : 归并排序
- odd_even_sort.py : 奇数偶数排序
- quicksort.py : 快排
- radix_sort.py : 基数排序
- selection_sort.py : 选择排序
4. 测试代码浅析
4.1 bubble_sort_test.py 源码分析
我们现在先忽略每个排序算法的具体实现。先看单元测试怎么写的。如果没有完备的测试, 很难保证功能代码的正确性。
挑选最简单的 bubble_sort_testt.py
来分析. 注释中 ##
开头的内容,是我增加的注释:
import unittest ## 使用 Python 标准库里的 unitest 框架来编写单元测试
import os ## 引入 os 模块
import sys ## 引入 sys 模块
## 考虑到了复用性, 基础的几种排序侧测试,已经在别的地方写好了,现在引入
from base_custom_comparison_sort_test import BaseCustomComparisonSortTest ## 引入基础的定制比较排序测试。
from base_positive_integer_sort_test import BasePositiveIntegerSortTest ## 引入正整数的排序测试
from base_negative_integer_sort_test import BaseNegativeIntegerSortTest ## 引入负整数的排序测试
from base_string_sort_test import BaseStringSortTest ## 引入基础字符串排序
sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, 'sort')) ## 把 sort 目录放入搜索目录
import bubble_sort ## 引入 sort 目录里的 bubble_sort 模块
## 开始编写正式的测试代码,是一个 class, 继承自 unitttest.TestCase 类, 传入了上面导入的几种排序测试类
class BubbleSortTest(unittest.TestCase,
BaseCustomComparisonSortTest,
BasePositiveIntegerSortTest,
BaseNegativeIntegerSortTest,
BaseStringSortTest):
## 使用2空格缩进
## 定义 setUp 函数: 这个函数在每次单元测试被执行的时候, 是第一句被执行的内容。
def setUp(self):
self.sort = bubble_sort.sort
if __name__ == '__main__':
unittest.main()
上述代码让人看的很晕, 其实主要内容是, 定义了一个 BubbleSortTest 类, 这是我们要测试的单元。这个类是继承了多个父类:
- unittest.TestCase
- BaseCustomComparisonSortTest
- BasePositiveIntegerSortTest
- BaseNegativeIntegerSortTest
- BaseStringSortTest
我们用不同颜色来区分不同的分组,每种颜色是一个父类中的测试用例:
结合父类代码中分析,我们整理为如下要阅读的代码, 就比较直观了: self.sort
是一个成员, 并且是一个函数。子类 BubbleSort
中执行的赋值 self.sort = bubble_sort.sort
, 相当于 C/C++ 中的函数函数指针, 其实就是回调函数:
class BasePositiveIntegerSortTest(object):
def test_sorts_empty_array(self):
self.assertEqual([], self.sort([]))
class BubbleSortTest(unittest.TestCase,
BaseCustomComparisonSortTest,
BasePositiveIntegerSortTest,
BaseNegativeIntegerSortTest,
BaseStringSortTest):
def setUp(self):
self.sort = bubble_sort.sort
# 子类自动继承了父类的函数,相当于这里有如下代码:
# def test_sorts_empty_array(self):
# self.assertEqual([], self.sort([]))
4.2 BasePositiveIntegerSortTest 源码分析
base_positive_integer_sort_test.py 的代码不多,都是测试用例。我们逐个看下:
class BasePositiveIntegerSortTest(object):
# 测试空的数组,排序结果也应该是空的
def test_sorts_empty_array(self):
self.assertEqual([], self.sort([]))
# 测试小型的有序数组,排序后应该和输入一样
# 其实这个测试代码写得不够好。应该避免重复写,可以提取为变量。
def test_sorts_small_sorted_array(self):
self.assertEqual([1,2,3,4,5], self.sort([1,2,3,4,5]))
# 测试小型的逆序数组
def test_sorts_small_reverse_sorted_array(self):
self.assertEqual([1,2,3,4,5], self.sort([5,4,3,2,1]))
# 测试小型的部分有序的数组
def test_sorts_small_sorted_array_with_two_values_swapped(self):
self.assertEqual([1,2,3,4,5], self.sort([1,2,5,4,3]))
# 测试大型的有序数组
def test_sorts_large_sorted_array(self):
self.assertEqual(
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,