Art of Unit Test (1), artunit

Source: Internet
Author: User

Art of Unit Test (1), artunit

  1 #!/usr/bin/env python   2 # encoding: utf-8   3   4 import unittest  5   6 """  7 the simplyest way to test return value   8 No needs to use stub  9 """ 10 class LogAnalyzer_0(object): 11     def IsValidLogFileName(self, fileName): 12         return str(fileName).endswith('.sln') 13 """ 14 However somethimes we have to rely on the extenal class or method  15 that we cannot control on it or it has not been finished yet 16 This is when we need stub to help us. eg, draw_from_weighted_range() and randrange(), interacting with filesystem.  17 Fakes here include stub (assert on CUT) and mock (assert on Fake) we talk about stub and mock in later posts. 18 Say our IsValidLogFileName() method needs read through the config file and return true if extension is supported in config file, 19  20 There two big types to inject fakes into MUT(Method Under Test): 21 1.Test are performed on the MUT itself (eg. assert(mut.dosomething(),true) 22     1.1 Abstracting concrete objects into interfaces or delegates 23         How: Extract an interface to allow replacing or extending underlying impl 24     1.2 Refactoring to allow injection of faked implementations of those delegates or interface. 25         How:  26         1.2.1.Inject stub in code under test using factory design (layer of indirection 2 faking a member in factory class) 27               the difference is that the object initiating the stub request is the code under test. 28               the fake instances was set by code external to the code under test before the test started in the below. 29               A test configures the factory class to re turn a stub object. The class usess the factory class to get the  30               stub instance, which in production code would return an object that is not a stub 31               Preferred to using this layer 32         1.2.2 Injection of a stub in test code (layer of indiretion 1 faking a member in class under test) 33             1.2.2.1 Inject stub via ctor (cumbersome whenyou have many dependencies) 34             1.2.2.2 Inject stub via setter/getter 35                         This is much simpler than ctor injection as each test can set only the dependencies 36                         that it needs to get the test underway; 37                         Use this when you want to signify that the dependency is optional or the dependency has  38                         a default instance created that does not create any problems; 39                  40         1.2.4.Inject stub impl via parameter 41 2.Test are performed on the class that inhetites from MUT (eg. assert(mut_child.dosomething(),true) 42     It is also known as Extract and override, which is is good to for sumulating inputs into your code under test 43     (in other words, return values from dependency). but it is cumbersome when you want t verify and check interactions  44     that are coming out of the code under test int othe dependency (in other words, it is good to play stub but very bad to play mock) 45      46     2.1 use local virtual factory method to get instance of stub 47         The time not to use this is there is an interface ready to fake or there is already a place that seam can be injected. 48     2.2 use extract and override to return a logical result instead of calling an actual denpendency 49         This uses a simple faked result instead of a stub 50         Much easier than 2.1 preferred to use 51 """ 52  53 # Refered to "1.1 Abstracting concrete objects into interfaces or delegates" 54 class ExtensionMgr_AbstractedInterface(object): 55     def IsValid(self, filename):  # should be overwriten by child  56         pass 57  58 class FileExtensionMgr_ConcreteImpl(ExtensionMgr_AbstractedInterface): 59     def IsValid(self, filename):  60         return str(filename).endswith('.sln')  61  62 # Stubs     63 class ExtendMgrStub(ExtensionMgr_AbstractedInterface): 64     def __init__(self): 65         self.mWillBeValid = False 66         return ExtensionMgr_AbstractedInterface.__init__(self) 67  68     def IsValid(self, filename): 69         return self.mWillBeValid 70  71 class ExtendMgrStub_WithoutIngeritingFrom_ExtensionMgr_AbstractedInterface(object): 72     def __init__(self): 73         self.mWillBeValid = False 74  75     def IsValid(self, filename): 76         return self.mWillBeValid 77  78      79 # Refered to 1.2.2.1 Inject stub impl via ctor (cumbersome whenyou have many dependencies)  80 class LogAnalyzer_StubInjectedViaCtor(object): 81     def __init__(self, iExtensionMgr): 82         self.mIExtensionMgr = iExtensionMgr 83  84     def IsValidLogFileName(self, fileName): 85         self.mIExtensionMgr.IsValid(fileName) 86          87 # Refered to "1.2.2.2 Inject stub impl via a setter and ggeter" 88 class LogAnalyzer_StubInjectedViaPropertySetter(object): 89     def __init__(self): 90         self.mIExtensionMgr = FileExtensionMgr_ConcreteImpl() 91  92     def IsValidLogFileName(self, fileName): 93         self.mIExtensionMgr.IsValid(fileName) 94  95     def SetIExtensionMgr(self, ext): 96         self.mIExtensionMgr = ext 97          98     def GetIExtensionMgr(self): 99         return self.mIExtensionMgr100 101 # Refered to "1.2.1.Inject stub in code under test using factory design"102 class ExtensionMgrFactory(object):103     iExtMgr = None104 105     @staticmethod106     def Create():107         # define factory that can use and return custom manager instance108         if ExtensionMgrFactory.iExtMgr is None:109             ExtensionMgrFactory.iExtMgr = FileExtensionMgr_ConcreteImpl()110         else:111             return ExtensionMgrFactory.iExtMgr112 113     @staticmethod114     def SetExtMgr(extmgr):115         ExtensionMgrFactory.iExtMgr = extmgr116 117 class LogAnalyzer_StubInjectedViaFactory(object):118     def __init__(self):119         self.mIExtensionMgr = ExtensionMgrFactory.Create()120     121     def IsValidLogFileName(self, fileName):122         self.mIExtensionMgr.IsValid(fileName)123         124 125 #Referred to "2.1 use local virtual factory method to get instance of stub"126 class LogAnalyzer_StubInjectedViaLocalFactoryMethod(object):127     def IsValidLogFileName(self, fileName):128         self.GetMgr().IsValid(fileName)129     def GetMgr(self):130         return FileExtensionMgr_ConcreteImpl()131 132 class TestableLogAnalyzer_ReturnStub(LogAnalyzer_StubInjectedViaLocalFactoryMethod):133     def __init__(self, iExtensionMgr):134         self.mIExtensionMgr = iExtensionMgr135     def GetMgr(self):136         return self.mIExtensionMgr137 138 139 #Referred to "2.2 use extract and override to return a logical result instead of calling an actual denpendency"140 class LogAnalyzer_OverrideMethodReturnsResult(object):141     def __init__(self):142         self.mIExtensionMgr =  FileExtensionMgr_ConcreteImpl()143     def IsValidLogFileName(self, fileName):144         self.IsValidExtension(fileName)145     def IsValidExtension(self,filename):146         return self.mIExtensionMgr.IsValid(filename)147 148 class TestableLogAnalyzer_OverrideMethodReturnsResult(LogAnalyzer_OverrideMethodReturnsResult):149     def __init__(self, is_valid_entension):150         self.is_valid_entension = is_valid_entension151     def IsValidExtension(self,filename):152         return self.is_valid_entension153 154 155 156 # cut means by class under test mut means by method under test157 class LogAnalyzerTestCase(unittest.TestCase):158 159     # No stub used just simply perform the test160     def test_IsValidLogFileName_BadExtension_ReturnFalse_NoStub(self):161         logAnalyzer0 = LogAnalyzer_0()162         ret = logAnalyzer0.IsValidLogFileName('fn1.sl')163         self.assertFalse(ret)164     165     # StubIjectedViaCtor 166     def test_IsValidLogFileName_BadExtension_ReturnFalse_StubIjectedViaCtor(self):167         ext = ExtendMgrStub()168         ext.mWillBeValid = False169         logAnalyzer = LogAnalyzer_StubInjectedViaCtor(ext)170         ret = logAnalyzer.IsValidLogFileName('fn1.sl')171         self.assertFalse(ret)172 173     # StubIjectedViaCtor174     # This is what I wrote because python is weak-type language175     # so it can still work without using inheratance176     def test_IsValidLogFileName_BadExtension_ReturnFalse_StubIjectedViaCtor_WithoutInhertingFrom_ExtensionMgr_AbstractedInterface(self):177         ext = ExtendMgrStub_WithoutIngeritingFrom_ExtensionMgr_AbstractedInterface()178         ext.mWillBeValid = False179 180         logAnalyzer = LogAnalyzer_StubInjectedViaCtor(ext)181         ret = logAnalyzer.IsValidLogFileName('fn1.sl')182 183         self.assertFalse(ret)184     185     # StubInjectedViaPropertySetter186     def test_IsValidLogFileName_BadExtension_ReturnFalse_StubInjectedViaPropertySetter(self):187         ext = ExtendMgrStub()188         ext.mWillBeValid = False189 190         logAnalyzer = LogAnalyzer_StubInjectedViaPropertySetter()191         logAnalyzer.SetIExtensionMgr(ext)192         ret = logAnalyzer.IsValidLogFileName('fn1.sl')193 194         self.assertFalse(ret)195 196     # StubIjectedViaFactory197     def test_IsValidLogFileName_BadExtension_ReturnFalse_4_StubIjectedViaFactory(self):198         ext = ExtendMgrStub()199         ext.mWillBeValid = False200         ExtensionMgrFactory.SetExtMgr(ext)201 202         logAnalyzer = LogAnalyzer_StubInjectedViaFactory()203         ret = logAnalyzer.IsValidLogFileName('fn1.sl')204 205         self.assertFalse(ret)206         207     # OverrideMethodReturnsResult208     def test_IsValidLogFileName_BadExtension_ReturnFalse_4_OverrideMethodReturnsResult(self):209         is_valid_extension = False210         211         testableLogAnalyzer = TestableLogAnalyzer_OverrideMethodReturnsResult(is_valid_extension)212         ret = testableLogAnalyzer.IsValidLogFileName('fnl.sl')213         214         self.assertFalse(ret)215         216 if __name__ == '__main__': 217     unittest.main()

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.