【问题标题】:Same tests over many similar data files对许多相似的数据文件进行相同的测试
【发布时间】:2014-03-23 13:19:26
【问题描述】:

使用 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

是否有任何软件包/方法可以使这项任务更容易?

【问题讨论】:

    标签: python unit-testing testing automated-tests


    【解决方案1】:

    受到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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多