如何在单个python脚本中设置测试数据和测试用例

时间:2019-01-30 04:09:22

标签: python unit-testing ddt

我正在编写一个单元测试,并试图在同一python脚本中设置用于测试用例的测试数据。

但是,当我运行脚本时,它会创建测试数据,但是会打印一条错误消息,指出该数据不存在,从而导致测试失败。只有当我再次运行脚本时,测试才能成功。

下面是我编写的简化脚本,用于了解发生了什么情况。

import unittest
from ddt import ddt, file_data
import pandas

@ddt
class TestWhatever(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.setup_test_data()
        print("setUpClass is running")

    @classmethod
    def tearDownClass(cls):
        print("tearDownClass is running")

    @classmethod
    def setup_test_data(cls):
        data = pandas.DataFrame({'msg':["testing"]})
        data = data.transpose()
        with open("practice_test.json", "w") as file:
           file.write(data.to_json())
        print("setup_test_data is running")

    @file_data("practice_test.json")
    def test_whatever_possible(self, msg):
        print("test_whatever_possible is running :", msg)
        self.assertEqual('q', 'q')

    def test_whatever_impossible(self):
        print("test_whatever_impossible is running")
        self.assertEqual('n', 'n')

当我运行上面的脚本时,它会打印:

setup_test_data is running
setUpClass is running
test_whatever_impossible is running
.EtearDownClass is running

======================================================================
ERROR: test_whatever_possible_00001_error (main.TestWhatever)
Error!
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\ddt.py", line 145, in wrapper
    return func(self, *args, **kwargs)
  File "C:\ddt.py", line 187, in func
    raise ValueError(message % file_attr)
ValueError: practice_test.json does not exist

----------------------------------------------------------------------
Ran 2 tests in 0.006s

FAILED (errors=1)

然后在第二次运行:

setup_test_data is running
setUpClass is running
test_whatever_impossible is running
.test_whatever_possible is running : testing
.tearDownClass is running

----------------------------------------------------------------------
Ran 2 tests in 0.005s

OK

我现在很迷路了... 有人对此有任何线索吗?

2 个答案:

答案 0 :(得分:0)

所有Python代码都是可执行的。加载类主体时,将执行其中的语句。装饰函数使用def中的咖啡创建函数,将其分配给临时类名称空间中的名称(例如test_whatever_possible),然后将其替换为调用装饰器的结果。

之所以如此重要,是因为在加载类时(而不是在运行测试时)会调用装饰器。装饰器file_data检查文件是否正确存在,然后(在那里)间接存在,因为它必须用用文件中的值调用测试的函数替换您的测试函数。

您的第二次运行已通过,因为第一次运行已创建测试文件。我建议在GitHub上填写问题。 file_data需要延迟打开文件,或者意外行为需要明确记录在某个地方。

您可以在source code中确切地看到此魔术发生的位置。file_data仅标记您的测试函数以进行进一步处理。 process_file_data然后检查文件是否可用于扩展实际测试,或创建一个替换文件,仅引起您看到的错误。

答案 1 :(得分:0)

作为解决方法,您可以编写自己的装饰器来创建数据文件,例如

def create_data(name):
    def decorator(fn):
        def decorated(*args, **kwargs):
            data = pandas.DataFrame({"msg": ["testing"]})
            data = data.transpose()
            with open(name, "w") as file:
                file.write(data.to_json())
            res = fn(*args, **kwargs)
            os.unlink(name)
            return res
        return decorated
    return decorator

,然后将其堆叠以进行测试(并删除setup_test_data步骤):

@ddt
class TestWhatever(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        print("setUpClass is running")

    @classmethod
    def tearDownClass(cls):
        print("tearDownClass is running")

    @create_data("practice_test.json")
    @file_data("practice_test.json")
    def test_whatever_possible(self):
        print("test_whatever_possible is running :")
        self.assertEqual("q", "q")

更新:1月31日

以下示例保留了将参数值传递到测试函数的ddt行为:

import json
import unittest
from ddt import ddt, FILE_ATTR


def create_file_data(value, data):
    def wrapper(func):
        with open(value, "w") as file:
            file.write(json.dumps(data))
        # this is what the file_data decorator does
        setattr(func, FILE_ATTR, value)
        return func

    return wrapper


@ddt
class TestWhatever(unittest.TestCase):
    @create_file_data("practice_test.json", {"msg": ["testing"]})
    def test_file_data(self, msg):
        print("test_file_data msg:", msg)


unittest.main()

运行此命令后,输出为:

test_file_data msg: ['testing']
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

使用上面的两个示例,您应该能够为您的问题找到合适的解决方案。