2014-02-21 3 views
0

с питоном и 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 

Есть ли какой-либо пакет/подход, чтобы облегчить задачу?

ответ

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 
Смежные вопросы