对许多类似数据文件的相同测试

时间:2014-02-21 20:20:32

标签: python unit-testing testing automated-tests

使用python和unittest我有测试目录的结构:

tests/
  __init__.py
  test_001.py
  data/
    data_001_in.py
    data_001_out.py

,其中

  • data_001_in.py:要在测试函数中使用的输入数据
  • data_001_out.py:从测试函数预期的输出数据

我在python词典中有输入和输出,因为它比使用json,sqlite等更容易。

我尝试使用一组具有相同格式的输入/输出数据,并对每对数据应用测试:

tests/
  __init__.py
  test_001.py
  data/
    data_001_in.py
    data_001_out.py
    data_002_in.py
    data_002_out.py
    data_003_in.py
    data_003_out.py

是否有任何方法/方法可以使此任务更容易?

1 个答案:

答案 0 :(得分:0)

在问题nose, unittest.TestCase and metaclass: auto-generated test_* methods not discovered中被启发,我用一个元类解决了。首先,我将目录数据结构更改为

├── data
│   ├── __init__.py
│   ├── data001
│   │   ├── __init__.py
│   │   ├── datain.py
│   │   ├── dataout.py
│   └── data002
│       ├── __init__.py
│       ├── datain.py
│       ├── dataout.py
└── metatest.py

其次,我使用子目录和基本测试中的数据创建了一个用于创建新测试的元类。

import unittest
import os
import copy

def data_dir():
    return os.path.join(os.path.dirname(__file__), 'data')

def get_subdirs(dir_name):
    """ retorna subdirectorios con path completo"""
    subdirs = []
    for f in os.listdir(dir_name):
        f_path = os.path.join(dir_name, f)
        if os.path.isdir(f_path):
            subdirs.append(f)
    return subdirs

def get_data_subdirs():
    return get_subdirs(data_dir())

def data_py_load(file_name):
    """ carga diccionario data desde archivo .py """
    name = file_name.split('.py')[0]
    path_name = 'data.' + name
    exec_str = "from {} import *".format(path_name)
    exec(exec_str)
    return data

class TestDirectories(type):

    def __new__(cls, name, bases, attrs):

        subdirs = get_data_subdirs()

        callables = dict([
            (meth_name, meth) for (meth_name, meth) in attrs.items() if
                meth_name.startswith('_test')
        ])

        data = {}
        for d in subdirs:
            data[d] = {}
            data[d]['name'] = d
            out_path = "{}.dataout.py".format(d)
            data[d]['out'] = data_py_load(out_path)
            var_path = "{}.datain.py".format(d)
            data[d]['in'] = data_py_load(var_path)

        for meth_name, meth in callables.items():
            for d in subdirs:
                new_meth_name = meth_name[1:]
                # name of test to add, _test to test
                test_name = "{}_{}".format(new_meth_name, d)
                # deep copy for dictionaries
                testeable = lambda self, func=meth, args=copy.deepcopy(data[d]): func(self, args)
                attrs[test_name] = testeable

        return type.__new__(cls, name, bases, attrs)

class TestData(unittest.TestCase):

    __metaclass__ = TestDirectories

    def _test_name(self, data):
        in_name = data['in']['name']
        out_name = data['out']['name']
        print in_name, out_name
        self.assertEquals(in_name, out_name)

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

而且,当我跑步时

$ python metatest.py
test_name_data001 (__main__.TestData) ... Alice Alice
ok
test_name_data002 (__main__.TestData) ... Bob Bob
ok

----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK