Python中如何从文件添加unittest测试用例?

近日学校软件测试实验课……任务需要做一个 func 函数做类似这样的工作(不使用库函数):

datetime.date(year,month,day)+datetime.timedelta(days =2)

函数实现问题不大,用元组输入输出,错误输入(月份,日期越界什么的)抛出异常,在网上了解到 unittest 这个工具,网上的教程以及官方文档中提及 testcase 都是直接把用例写在代码里,不知有没有从外部文件导入测试用例的方法?


Python中如何从文件添加unittest测试用例?

7 回复

啊…写的时候突然想到异常怎么做,就改了正文然而没改标题…


在Python的unittest框架里,从文件动态添加测试用例是个挺常见的需求,特别是当你的测试用例数据是外部存储的时候。核心思路就是用TestLoaderloadTestsFromNameloadTestsFromTestCase方法,或者直接构建TestSuite

下面给你一个最直接、好用的方法。假设你有一个文件test_data.txt,里面每行是一个测试用例要用的输入,你想为每行数据跑一个测试。

1. 准备测试数据文件 (test_data.txt):

foo
bar
baz

2. 创建测试脚本 (run_file_based_tests.py):

import unittest
import sys

def load_test_cases_from_file(filename):
    """从文件读取数据,生成测试用例"""
    test_cases = []
    with open(filename, 'r') as f:
        for line_num, line in enumerate(f, start=1):
            value = line.strip()
            if value:  # 忽略空行
                # 这里根据你的实际测试逻辑来定义测试方法
                # 我们创建一个动态的测试方法
                def test_method(self, val=value):
                    # 示例断言:检查字符串是否全小写
                    self.assertTrue(val.islower(), f"'{val}' should be lowercase")
                
                # 给方法一个唯一的名字
                test_name = f'test_line_{line_num}_{value}'
                test_method.__name__ = test_name
                test_cases.append((test_name, test_method))
    return test_cases

def create_test_class(test_cases):
    """动态创建测试类"""
    # 用type动态创建类
    attrs = {name: method for name, method in test_cases}
    return type('FileDataTest', (unittest.TestCase,), attrs)

if __name__ == '__main__':
    # 从文件加载测试数据
    cases = load_test_cases_from_file('test_data.txt')
    
    if not cases:
        print("No test cases found in file!")
        sys.exit(0)
    
    # 创建测试类
    TestClass = create_test_class(cases)
    
    # 运行测试
    suite = unittest.TestLoader().loadTestsFromTestCase(TestClass)
    runner = unittest.TextTestRunner(verbosity=2)
    runner.run(suite)

3. 运行它:

python run_file_based_tests.py

输出会是这样的:

test_line_1_foo (__main__.FileDataTest) ... ok
test_line_2_bar (__main__.FileDataTest) ... ok
test_line_3_baz (__main__.FileDataTest) ... ok

----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK

关键点解释:

  • load_test_cases_from_file 函数负责读取文件,并为每一行(或你定义的每个数据单元)生成一个唯一的测试方法名和对应的测试函数。
  • create_test_class 使用 type() 动态地创建一个继承自 unittest.TestCase 的新类,并把上一步生成的所有测试方法作为它的属性。
  • 最后用标准的 TestLoader 加载这个动态创建的类并运行。

更简洁的写法(如果逻辑简单): 如果你觉得上面动态创建类有点绕,还有个更直接的土办法,直接在运行时修改已有的测试类:

import unittest

class TestFromFile(unittest.TestCase):
    pass

# 动态添加测试方法
with open('test_data.txt', 'r') as f:
    for i, line in enumerate(f, 1):
        value = line.strip()
        if value:
            def make_test(val):
                return lambda self: self.assertTrue(val.islower())
            setattr(TestFromFile, f'test_{i}_{value}', make_test(value))

if __name__ == '__main__':
    unittest.main()

总结建议:用 loadTestsFromTestCase 配合动态生成的测试类最靠谱。

有的,还可以写在 xml file 里方便后期更改

我们有个很老的框架是用 excel 组织的用例.用例都是类似函数一样的。然后用 java 里面的反射来执行真正的函数

doctest 也可以独立文件的~


x.py

<br>def add(a, b): <br> return a + b<br>

case.txt

<br>&gt;&gt;&gt; from x import add <br>&gt;&gt;&gt; add(1, 2) <br>3 <br>&gt;&gt;&gt; add(3, 97) <br>100 <br>&gt;&gt;&gt; add(3, 3) != 5 <br>True<br>

<br>$ python -m doctest -v case.txt<br>Trying:<br> from x import add<br>Expecting nothing<br>ok<br>Trying:<br> add(1, 2)<br>Expecting:<br> 3<br>ok<br>Trying:<br> add(3, 97)<br>Expecting:<br> 100<br>ok<br>Trying:<br> add(3, 3) != 5<br>Expecting:<br> True<br>ok<br>1 items passed all tests:<br> 4 tests in case.txt<br>4 tests in 1 items.<br>4 passed and 0 failed.<br>Test passed.<br>

https://docs.python.org/2/library/doctest.html

啊,确实用 xml 之类的比 csv 方便很多
不懂 Java,不过提供了一个好思路
谢谢你的代码…如果从文件中获取数据例如
2016 2 30
2017 3 26
当作测试数据,不知道是否可行?

回到顶部