2016-04-25 45 views
0

我试图做类似下面的东西:DI与应用程序中从别处调用的单元测试?

import unittest 

class foo: 
    one = 1 
    two = 1 

class bar: 
    one = 2 
    two = 2 


class my_test(unittest.TestCase): 

    def __init__(self, di_source): 
     self.di = di_source 
     print 'initing my_test' 

    def setUp(self): 
     print 'setting up!' 

    def tearDown(self): 
     print 'tearing down :(' 

    def test_case_one(self): 
     self.assertEqual(self.di.one,1) 

    def test_case_two(self): 
     self.assertEqual(self.di.two, 2) 


di_one = foo() 
di_two = bar() 

# called from elsewhere in my application 
test_one = my_test(di_one).run() 
test_one = my_test(di_two).run() 

我的目标是:

  • 能够调用run()上一个测试套件
  • 提供一个DI容器在运行时测试套件
  • 利用setUptearDown功能提供的单元测试框架

但是,似乎当我试图做到这一点的单元测试框架不喜欢我的构造函数:

AttributeError: 'my_test' object has no attribute '_testMethodName' 

是否有更好的方法来组织这个例子来避免这个问题?

+0

你的例子强调了你如何用错误的参数调用TestCase。您可以使用方法名称来调用它,而不是自定义对象。 使用my_test('test_case_one'),或用这些参数调用基础构造函数。 –

回答

1

如何使用这样的事情:

这使您可以为单个套件创建共享资源,资源传递给所有的单元测试,然后用多种方法测试的对象。

'''Example using a shared resource in a unittest''' 


import unittest 


def callable_function(): 
    '''Generic callable_function, this should actually be connected to an object constructor or something else'' 

    return {'a': 3} 


class MyTest(unittest.TestCase): 
    '''Custom unittest test case''' 

    def __init__(self, resource, method_name): 
     super(MyTest, self).__init__(method_name) 

     self._resource = resource 

    def test_getitem(self): 
     '''Test getting item''' 

     self.assertEquals(self._resource['a'], 3) 

    def test_setitem(self): 
     '''Test getting item''' 

     self._resource['b'] = 2 
     self.assertEquals(self._resource['b'], 2) 

    def test_mutable(self): 
     '''Test changes persist across tests''' 

     self.assertEquals(self._resource['b'], 2) 


def run_suite(): 
    '''Run complete unittest suite''' 

    suite = unittest.TestSuite() 
    item = callable_function() 

    suite.addTests([ 
     MyTest(item, 'test_getitem'), 
     MyTest(item, 'test_setitem'), 
     MyTest(item, 'test_mutable'), 
    ]) 

    runner = unittest.TextTestRunner() 
    runner.run(suite) 


if __name__ == '__main__': 
    run_suite() 

编辑:如果你需要去发现的飞行方法,你可以做到以下几点:

import inspect 

def get_tests(cls): 
    return [k for k, v in cls.__dict__.items() if k.startswith('test') and inspect.ismethod(v)] 

for name in get_tests(MyTest): 
    suite.addTest(MyTest(resource, name)) 

的想法很简单:覆盖__init__方法,因此它需要的资源和方法名,将资源绑定到该类,然后像平常一样初始化TestCase

运行测试时,只使用绑定资源。

+0

这对我来说很有用,我认为。我不喜欢复制/粘贴的方法名称,但这比我认为的更好! – enderland

+0

如果您需要发现方法,请参阅我的编辑。 –