2016-04-25 46 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

如果您需要發現方法,請參閱我的編輯。 –