11from unittest import TestCase as BaseTestCase
2- from typing import Any , Dict
2+ from typing import Any , Dict , Tuple
33from abc import abstractmethod
44from warnings import warn
55from copy import deepcopy
@@ -12,51 +12,69 @@ class TestCase(BaseTestCase):
1212 Extends unittest.TestCase with methods that assert the result of a defined
1313 `subject` method.
1414
15- ```
16- from unittest_extensions import TestCase, args
15+ Inherit from this class for your test-case classes and decorate test methods
16+ with the @ args decorator.
1717
18+ Examples:
19+ >>> from unittest_extensions import TestCase, args
1820
19- class MyClass:
20- def my_method(self, a, b):
21- return a + b
21+ >>> class MyClass:
22+ ... def my_method(self, a, b):
23+ ... return a + b
2224
25+ >>> class TestMyMethod(TestCase):
26+ ... def subject(self, a, b):
27+ ... return MyClass().my_method(a, b)
2328
24- class TestMyMethod(TestCase):
25- def subject (self, a, b ):
26- return MyClass().my_method(a, b )
29+ ... @args(None, 2)
30+ ... def test_none_plus_int (self):
31+ ... self.assertResultRaises(TypeError )
2732
28- @args({"a": None, "b": 2} )
29- def test_none_plus_int (self):
30- self.assertResultRaises(TypeError )
33+ ... @args(a=10, b=22.1 )
34+ ... def test_int_plus_float (self):
35+ ... self.assertResult(32.1 )
3136
32- @args({"a": 10, "b": 22.1})
33- def test_int_plus_float(self):
34- self.assertResult(32.1)
35- ```
37+ ... @args("1", b="2")
38+ ... def test_str_plus_str(self):
39+ ... self.assertResult("12")
3640 """
3741
3842 @abstractmethod
39- def subject (self , ** kwargs ) -> Any : ...
43+ def subject (self , * args , ** kwargs ) -> Any :
44+ raise TestError ("No 'subject' method found; perhaps you mispelled it?" )
4045
4146 def subjectKwargs (self ) -> Dict [str , Any ]:
4247 """
4348 Return the keyword arguments of the subject.
4449
45- The dictionary returned is a copy of the original arguments. Thus,
50+ The dictionary returned is a deep copy of the original arguments. Thus,
4651 the arguments that the subject receives cannot be mutated by mutating
4752 the returned object of this method.
4853 """
4954 # NOTE: deepcopy keeps a reference of the copied object. This can cause
5055 # issues with memory.
5156 return deepcopy (self ._subjectKwargs )
5257
58+ def subjectArgs (self ) -> Tuple :
59+ """
60+ Return the positional arguments of the subject.
61+
62+ The tuple returned is a deep copy of the original arguments. Thus,
63+ the arguments that the subject receives cannot be mutated by mutating
64+ the returned object of this method.
65+ """
66+ # NOTE: deepcopy keeps a reference of the copied object. This can cause
67+ # issues with memory.
68+ return deepcopy (self ._subjectArgs )
69+
5370 def result (self ) -> Any :
5471 """
55- Result of the `subject` called with arguments defined by the `args`
56- decorator.
72+ Result of the `subject` called with arguments defined by the `args` decorator.
5773 """
5874 try :
59- self ._subjectResult = self .subject (** self ._subjectKwargs )
75+ self ._subjectResult = self .subject (
76+ * self ._subjectArgs , ** self ._subjectKwargs
77+ )
6078 return self ._subjectResult
6179 except Exception as e :
6280 if len (e .args ) == 0 :
@@ -328,6 +346,11 @@ def assertResultDict(self, dct):
328346 self .assertDictEqual (self .result (), dct )
329347
330348 def _callTestMethod (self , method ):
349+ if hasattr (method , "_subjectArgs" ):
350+ self ._subjectArgs = method ._subjectArgs
351+ else :
352+ self ._subjectArgs = tuple ()
353+
331354 if hasattr (method , "_subjectKwargs" ):
332355 self ._subjectKwargs = method ._subjectKwargs
333356 else :
@@ -341,3 +364,4 @@ def _callTestMethod(self, method):
341364 stacklevel = 3 ,
342365 )
343366 self ._subjectKwargs = {}
367+ self ._subjectArgs = tuple ()
0 commit comments