Skip to content

Commit e9401c1

Browse files
committed
Run myunit test modules individually
1 parent afd6bfc commit e9401c1

21 files changed

+145
-257
lines changed

mypy/checkstrformat.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
from mypy.nodes import (
1111
Node, StrExpr, TupleExpr, DictExpr, Context
1212
)
13-
import mypy.checker
13+
if False:
14+
# break import cycle only needed for mypy
15+
import mypy.checker
1416
from mypy import messages
1517
from mypy.messages import MessageBuilder
1618

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import codecs
2+
import sys
23

34
from unittest import TestCase
45

@@ -8,68 +9,68 @@
89
# even indices are input functions, odd indices are expected output
910
test_function_examples = [
1011
# test a function without annotations
11-
'''\
12+
b'''\
1213
def f(x):
1314
x = {'a': x}
1415
return x['a']
1516
''',
16-
'''\
17+
b'''\
1718
def f(x):
1819
x = {'a': x}
1920
return x['a']
2021
''',
2122

2223
# test parameter type annotations
23-
'''\
24+
b'''\
2425
def f(x: int, y: str = 'abc'):
2526
return x
2627
''',
27-
'''\
28+
b'''\
2829
def f(x , y = 'abc'):
2930
return x
3031
''',
3132

3233
# test return type annotations
33-
'''\
34+
b'''\
3435
def f(x, y) -> str:
3536
return x
3637
''',
37-
'''\
38+
b'''\
3839
def f(x, y) :
3940
return x
4041
''',
4142

4243
# test newlines in param list
43-
'''\
44+
b'''\
4445
def f(x: int,
4546
y: str) -> str:
4647
return x
4748
''',
48-
'''\
49+
b'''\
4950
def f(x ,
5051
y ) :
5152
return x
5253
''',
5354

5455
# test newlines in return type annotation
55-
'''\
56+
b'''\
5657
def f(x: int, y: str='abc') -> Tuple[int,
5758
str]:
5859
return x, y
5960
''',
60-
'''\
61+
b'''\
6162
def f(x , y ='abc')\\
6263
:
6364
return x, y
6465
''',
6566

6667

6768
# test unrelated continuations
68-
'''\
69+
b'''\
6970
x = 1 + \
7071
2
7172
''',
72-
'''\
73+
b'''\
7374
x = 1 + \
7475
2
7576
''',
@@ -81,7 +82,11 @@ class TestFunctionTranslation(TestCase):
8182

8283
def test_all_functions(self):
8384
for i in range(0, len(test_function_examples), 2):
84-
func_translated = codecs.decode(test_function_examples[i], 'mypy')
85-
#print repr(func_translated)
86-
#print repr(test_function_examples[i + 1])
87-
self.assertEqual(func_translated, test_function_examples[i + 1])
85+
func_orig = test_function_examples[i]
86+
func_py2 = test_function_examples[i + 1].decode('utf-8')
87+
func_py3 = func_orig.decode('utf-8')
88+
func_translated = codecs.decode(func_orig, 'mypy')
89+
if sys.version_info[0] == 2:
90+
self.assertEqual(func_translated, func_py2)
91+
else:
92+
self.assertEqual(func_translated, func_py3)

mypy/myunit.py renamed to mypy/myunit/__init__.py

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import importlib
12
import os
23
import sys
34
import re
@@ -13,6 +14,8 @@
1314
is_quiet = False
1415
patterns = [] # type: List[str]
1516
times = [] # type: List[Tuple[float, str]]
17+
APPEND_TESTCASES = ''
18+
UPDATE_TESTCASES = False
1619

1720

1821
class AssertionFailure(Exception):
@@ -151,12 +154,38 @@ def skip(self) -> None:
151154
raise SkipTestCaseException()
152155

153156

154-
def run_test(t: Suite, args: List[str] = None) -> None:
157+
def add_suites_from_module(suites: List[Suite], mod_name: str) -> None:
158+
mod = importlib.import_module(mod_name)
159+
got_suite = False
160+
for suite in mod.__dict__.values():
161+
if isinstance(suite, type) and issubclass(suite, Suite) and suite is not Suite:
162+
got_suite = True
163+
suites.append(suite())
164+
if not got_suite:
165+
# Sanity check in case e.g. it uses unittest instead of a myunit.
166+
# The codecs tests do since they need to be python2-compatible.
167+
sys.exit('Test module %s had no test!' % mod_name)
168+
169+
class ListSuite(Suite):
170+
def __init__(self, suites: List[Suite]) -> None:
171+
for suite in suites:
172+
mod_name = type(suite).__module__.replace('.', '_')
173+
mod_name = mod_name.replace('mypy_', '')
174+
mod_name = mod_name.replace('test_', '')
175+
mod_name = mod_name.strip('_').replace('__', '_')
176+
type_name = type(suite).__name__
177+
name = 'test_%s_%s' % (mod_name, type_name)
178+
setattr(self, name, suite)
179+
super().__init__()
180+
181+
def main(args: List[str] = None) -> None:
155182
global patterns, is_verbose, is_quiet
183+
global APPEND_TESTCASES, UPDATE_TESTCASES
156184
if not args:
157-
args = []
185+
args = sys.argv[1:]
158186
is_verbose = False
159187
is_quiet = False
188+
suites = [] # type: List[Suite]
160189
patterns = []
161190
i = 0
162191
while i < len(args):
@@ -165,17 +194,28 @@ def run_test(t: Suite, args: List[str] = None) -> None:
165194
is_verbose = True
166195
elif a == '-q':
167196
is_quiet = True
168-
# Used for updating tests, but breaks clean code usage.
169-
elif a in ('-u', '-i'):
170-
pass
171-
elif len(a) > 0 and a[0] != '-':
197+
elif a == '-u':
198+
APPEND_TESTCASES = '.new'
199+
UPDATE_TESTCASES = True
200+
elif a == '-i':
201+
APPEND_TESTCASES = ''
202+
UPDATE_TESTCASES = True
203+
elif a == '-m':
204+
i += 1
205+
if i == len(args):
206+
sys.exit('-m requires an argument')
207+
add_suites_from_module(suites, args[i])
208+
elif not a.startswith('-'):
172209
patterns.append(a)
173210
else:
174-
raise ValueError('Invalid arguments')
211+
sys.exit('Usage: python -m mypy.myunit [-v] [-q] [-u | -i] -m test.module [-m test.module ...] [filter ...]')
175212
i += 1
176213
if len(patterns) == 0:
177214
patterns.append('*')
215+
if not suites:
216+
sys.exit('At least one -m argument is required')
178217

218+
t = ListSuite(suites)
179219
num_total, num_fail, num_skip = run_test_recursive(t, 0, 0, 0, '', 0)
180220

181221
skip_msg = ''

mypy/myunit/__main__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# This is a separate module from mypy.myunit so it doesn't exist twice.
2+
from mypy.myunit import main
3+
4+
if __name__ == '__main__':
5+
main()

mypy/nodes.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ class Context(metaclass=ABCMeta):
2020
def get_line(self) -> int: pass
2121

2222

23-
import mypy.types
23+
if False:
24+
# break import cycle only needed for mypy
25+
import mypy.types
2426

2527

2628
T = TypeVar('T')

mypy/subtypes.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
)
88
import mypy.applytype
99
import mypy.constraints
10+
# Circular import; done in the function instead.
11+
#import mypy.solve
1012
from mypy import messages, sametypes
1113
from mypy.nodes import TypeInfo
1214
from mypy.expandtype import expand_type
@@ -232,6 +234,7 @@ def unify_generic_callable(type: CallableType, target: CallableType) -> Callable
232234
233235
Return unified CallableType if successful; otherwise, return None.
234236
"""
237+
import mypy.solve
235238
constraints = [] # type: List[mypy.constraints.Constraint]
236239
for arg_type, target_arg_type in zip(type.arg_types, target.arg_types):
237240
c = mypy.constraints.infer_constraints(

mypy/test/testcheck.py

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,15 @@
55
import typing
66

77
from mypy import build
8-
from mypy.myunit import Suite, run_test
8+
import mypy.myunit # for mutable globals (ick!)
9+
from mypy.myunit import Suite
910
from mypy.test.config import test_temp_dir, test_data_prefix
1011
from mypy.test.data import parse_test_cases
1112
from mypy.test.helpers import assert_string_arrays_equal, testcase_pyversion, update_testcase_output
1213
from mypy.test.testsemanal import normalize_error_messages
1314
from mypy.errors import CompileError
1415

1516
import sys
16-
APPEND_TESTCASES = '.new' if '-u' in sys.argv else ''
17-
UPDATE_TESTCASES = '-i' in sys.argv or '-u' in sys.argv
1817

1918
# List of files that contain test case descriptions.
2019
files = [
@@ -73,15 +72,10 @@ def run_test(self, testcase):
7372
except CompileError as e:
7473
a = normalize_error_messages(e.messages)
7574

76-
if testcase.output != a and UPDATE_TESTCASES:
77-
update_testcase_output(testcase, a, APPEND_TESTCASES)
75+
if testcase.output != a and mypy.myunit.UPDATE_TESTCASES:
76+
update_testcase_output(testcase, a, mypy.myunit.APPEND_TESTCASES)
7877

7978
assert_string_arrays_equal(
8079
testcase.output, a,
8180
'Invalid type checker output ({}, line {})'.format(
8281
testcase.file, testcase.line))
83-
84-
85-
if __name__ == '__main__':
86-
import sys
87-
run_test(TypeCheckSuite(), sys.argv[1:])

mypy/test/testinfer.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import typing
44

5-
from mypy.myunit import Suite, assert_equal, assert_true, run_test
5+
from mypy.myunit import Suite, assert_equal, assert_true
66
from mypy.checkexpr import map_actuals_to_formals
77
from mypy.nodes import ARG_POS, ARG_OPT, ARG_STAR, ARG_STAR2, ARG_NAMED
88
from mypy.types import AnyType, TupleType
@@ -205,8 +205,3 @@ def expand_callee_kinds(kinds_and_names):
205205
kinds.append(v)
206206
names.append(None)
207207
return kinds, names
208-
209-
210-
if __name__ == '__main__':
211-
import sys
212-
run_test(MapActualsToFormalsSuite(), sys.argv[1:])

mypy/test/testopgen.py

Lines changed: 0 additions & 74 deletions
This file was deleted.

mypy/test/testparse.py

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import typing
88

9-
from mypy.myunit import Suite, AssertionFailure, run_test
9+
from mypy.myunit import Suite, AssertionFailure
1010
from mypy.test.helpers import assert_string_arrays_equal
1111
from mypy.test.data import parse_test_cases
1212
from mypy.test import config
@@ -72,15 +72,3 @@ def test_parse_error(testcase):
7272
testcase.output, e.messages,
7373
'Invalid compiler output ({}, line {})'.format(testcase.file,
7474
testcase.line))
75-
76-
77-
class CombinedParserSuite(Suite):
78-
def __init__(self):
79-
self.test_parse = ParserSuite()
80-
self.test_parse_errors = ParseErrorSuite()
81-
super().__init__()
82-
83-
84-
if __name__ == '__main__':
85-
import sys
86-
run_test(CombinedParserSuite(), sys.argv[1:])

0 commit comments

Comments
 (0)