1
1
from unittest import TestCase as BaseTestCase
2
- from typing import Any , Dict
2
+ from typing import Any , Dict , Tuple
3
3
from abc import abstractmethod
4
4
from warnings import warn
5
5
from copy import deepcopy
@@ -12,51 +12,69 @@ class TestCase(BaseTestCase):
12
12
Extends unittest.TestCase with methods that assert the result of a defined
13
13
`subject` method.
14
14
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.
17
17
18
+ Examples:
19
+ >>> from unittest_extensions import TestCase, args
18
20
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
22
24
25
+ >>> class TestMyMethod(TestCase):
26
+ ... def subject(self, a, b):
27
+ ... return MyClass().my_method(a, b)
23
28
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 )
27
32
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 )
31
36
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")
36
40
"""
37
41
38
42
@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?" )
40
45
41
46
def subjectKwargs (self ) -> Dict [str , Any ]:
42
47
"""
43
48
Return the keyword arguments of the subject.
44
49
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,
46
51
the arguments that the subject receives cannot be mutated by mutating
47
52
the returned object of this method.
48
53
"""
49
54
# NOTE: deepcopy keeps a reference of the copied object. This can cause
50
55
# issues with memory.
51
56
return deepcopy (self ._subjectKwargs )
52
57
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
+
53
70
def result (self ) -> Any :
54
71
"""
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.
57
73
"""
58
74
try :
59
- self ._subjectResult = self .subject (** self ._subjectKwargs )
75
+ self ._subjectResult = self .subject (
76
+ * self ._subjectArgs , ** self ._subjectKwargs
77
+ )
60
78
return self ._subjectResult
61
79
except Exception as e :
62
80
if len (e .args ) == 0 :
@@ -328,6 +346,11 @@ def assertResultDict(self, dct):
328
346
self .assertDictEqual (self .result (), dct )
329
347
330
348
def _callTestMethod (self , method ):
349
+ if hasattr (method , "_subjectArgs" ):
350
+ self ._subjectArgs = method ._subjectArgs
351
+ else :
352
+ self ._subjectArgs = tuple ()
353
+
331
354
if hasattr (method , "_subjectKwargs" ):
332
355
self ._subjectKwargs = method ._subjectKwargs
333
356
else :
@@ -341,3 +364,4 @@ def _callTestMethod(self, method):
341
364
stacklevel = 3 ,
342
365
)
343
366
self ._subjectKwargs = {}
367
+ self ._subjectArgs = tuple ()
0 commit comments