1
1
#! /usr/bin/env python3
2
+ from pathlib import Path
2
3
import argparse
3
4
import errno
4
- import fnmatch
5
5
import json
6
6
import os
7
7
import random
@@ -28,119 +28,133 @@ else:
28
28
}
29
29
30
30
31
- ROOT_DIR = os .path .abspath (
32
- os .path .join (os .path .dirname (__file__ ), os .pardir ).rstrip ("__pycache__" ),
33
- )
34
- SUITE_ROOT_DIR = os .path .join (ROOT_DIR , "tests" )
35
- REMOTES_DIR = os .path .join (ROOT_DIR , "remotes" )
36
-
31
+ ROOT_DIR = Path (__file__ ).parent .parent
32
+ SUITE_ROOT_DIR = ROOT_DIR / "tests"
33
+ REMOTES_DIR = ROOT_DIR / "remotes"
37
34
38
- with open (os .path .join (ROOT_DIR , "test-schema.json" )) as schema :
39
- TESTSUITE_SCHEMA = json .load (schema )
35
+ TESTSUITE_SCHEMA = json .loads ((ROOT_DIR / "test-schema.json" ).read_text ())
40
36
41
37
42
38
def files (paths ):
43
39
"""
44
- Each test file in the provided paths.
40
+ Each test file in the provided paths, as an array of test cases .
45
41
"""
46
42
for path in paths :
47
- with open (path ) as test_file :
48
- yield json .load (test_file )
43
+ yield json .loads (path .read_text ())
49
44
50
45
51
- def groups (paths ):
46
+ def cases (paths ):
52
47
"""
53
- Each test group within each file in the provided paths.
48
+ Each test case within each file in the provided paths.
54
49
"""
55
50
for test_file in files (paths ):
56
- for group in test_file :
57
- yield group
51
+ yield from test_file
58
52
59
53
60
- def cases (paths ):
54
+ def tests (paths ):
61
55
"""
62
- Each individual test case within all groups within the provided paths.
56
+ Each individual test within all cases within the provided paths.
63
57
"""
64
- for test_group in groups (paths ):
65
- for test in test_group ["tests" ]:
66
- test ["schema" ] = test_group ["schema" ]
58
+ for case in cases (paths ):
59
+ for test in case ["tests" ]:
60
+ test ["schema" ] = case ["schema" ]
67
61
yield test
68
62
69
63
70
64
def collect (root_dir ):
71
65
"""
72
66
All of the test file paths within the given root directory, recursively.
73
67
"""
74
- for root , _ , files in os .walk (root_dir ):
75
- for filename in fnmatch .filter (files , "*.json" ):
76
- yield os .path .join (root , filename )
68
+ return root_dir .glob ("**/*.json" )
77
69
78
70
79
71
class SanityTests (unittest .TestCase ):
80
72
@classmethod
81
73
def setUpClass (cls ):
82
- print ("Looking for tests in %s" % SUITE_ROOT_DIR )
83
- print ("Looking for remotes in %s" % REMOTES_DIR )
74
+ print (f"Looking for tests in { SUITE_ROOT_DIR } " )
75
+ print (f"Looking for remotes in { REMOTES_DIR } " )
76
+
84
77
cls .test_files = list (collect (SUITE_ROOT_DIR ))
85
- cls .remote_files = list (collect (REMOTES_DIR ))
86
- print ("Found %s test files" % len (cls .test_files ))
87
- print ("Found %s remote files" % len (cls .remote_files ))
88
78
assert cls .test_files , "Didn't find the test files!"
79
+ print (f"Found { len (cls .test_files )} test files" )
80
+
81
+ cls .remote_files = list (collect (REMOTES_DIR ))
89
82
assert cls .remote_files , "Didn't find the remote files!"
83
+ print (f"Found { len (cls .remote_files )} remote files" )
90
84
91
85
def test_all_test_files_are_valid_json (self ):
86
+ """
87
+ All test files contain valid JSON.
88
+ """
92
89
for path in self .test_files :
93
- with open (path ) as test_file :
94
- try :
95
- json .load (test_file )
96
- except ValueError as error :
97
- self .fail ("%s contains invalid JSON (%s)" % (path , error ))
90
+ try :
91
+ json .loads (path .read_text ())
92
+ except ValueError as error :
93
+ self .fail (f"{ path } contains invalid JSON ({ error } )" )
98
94
99
95
def test_all_remote_files_are_valid_json (self ):
96
+ """
97
+ All remote files contain valid JSON.
98
+ """
100
99
for path in self .remote_files :
101
- with open (path ) as remote_file :
102
- try :
103
- json .load (remote_file )
104
- except ValueError as error :
105
- self .fail ("%s contains invalid JSON (%s)" % (path , error ))
100
+ try :
101
+ json .loads (path .read_text ())
102
+ except ValueError as error :
103
+ self .fail (f"{ path } contains invalid JSON ({ error } )" )
106
104
107
105
def test_all_descriptions_have_reasonable_length (self ):
108
- for case in cases (self .test_files ):
109
- description = case ["description" ]
106
+ """
107
+ All tests have reasonably long descriptions.
108
+ """
109
+ for count , test in enumerate (tests (self .test_files )):
110
+ description = test ["description" ]
110
111
self .assertLess (
111
112
len (description ),
112
113
70 ,
113
- "%r is too long! (keep it to less than 70 chars)" % (
114
- description ,
115
- ),
114
+ f"{ description !r} is too long! (keep it to less than 70 chars)"
116
115
)
116
+ print (f"Found { count } tests." )
117
117
118
118
def test_all_descriptions_are_unique (self ):
119
- for group in groups (self .test_files ):
120
- descriptions = set (test ["description" ] for test in group ["tests" ])
119
+ """
120
+ All test cases have unique test descriptions in their tests.
121
+ """
122
+ for count , case in enumerate (cases (self .test_files )):
123
+ descriptions = set (test ["description" ] for test in case ["tests" ])
121
124
self .assertEqual (
122
125
len (descriptions ),
123
- len (group ["tests" ]),
124
- "%r contains a duplicate description" % ( group ,)
126
+ len (case ["tests" ]),
127
+ f" { case !r } contains a duplicate description",
125
128
)
129
+ print (f"Found { count } test cases." )
126
130
127
131
@unittest .skipIf (jsonschema is None , "Validation library not present!" )
128
132
def test_all_schemas_are_valid (self ):
129
- for version in os .listdir (SUITE_ROOT_DIR ):
130
- Validator = VALIDATORS .get (version )
133
+ """
134
+ All schemas are valid under their metaschemas.
135
+ """
136
+ for version in SUITE_ROOT_DIR .iterdir ():
137
+ if not version .is_dir ():
138
+ continue
139
+
140
+ Validator = VALIDATORS .get (version .name )
131
141
if Validator is not None :
132
- test_files = collect (os . path . join ( SUITE_ROOT_DIR , version ) )
142
+ test_files = collect (version )
133
143
for case in cases (test_files ):
134
144
try :
135
145
Validator .check_schema (case ["schema" ])
136
146
except jsonschema .SchemaError as error :
137
- self .fail ("%s contains an invalid schema (%s)" %
138
- (case , error ))
147
+ self .fail (
148
+ f"{ case } contains an invalid schema ({ error } )" ,
149
+ )
139
150
else :
140
- warnings .warn ("No schema validator for %s" % schema )
151
+ warnings .warn (f "No schema validator for { version . name } " )
141
152
142
153
@unittest .skipIf (jsonschema is None , "Validation library not present!" )
143
154
def test_suites_are_valid (self ):
155
+ """
156
+ All test files are valid under test-schema.json.
157
+ """
144
158
Validator = jsonschema .validators .validator_for (TESTSUITE_SCHEMA )
145
159
validator = Validator (TESTSUITE_SCHEMA )
146
160
for tests in files (self .test_files ):
@@ -153,7 +167,7 @@ class SanityTests(unittest.TestCase):
153
167
def main (arguments ):
154
168
if arguments .command == "check" :
155
169
suite = unittest .TestLoader ().loadTestsFromTestCase (SanityTests )
156
- result = unittest .TextTestRunner (verbosity = 2 ).run (suite )
170
+ result = unittest .TextTestRunner ().run (suite )
157
171
sys .exit (not result .wasSuccessful ())
158
172
elif arguments .command == "flatten" :
159
173
selected_cases = [case for case in cases (collect (arguments .version ))]
@@ -166,20 +180,17 @@ def main(arguments):
166
180
remotes = {}
167
181
for path in collect (REMOTES_DIR ):
168
182
relative_path = os .path .relpath (path , REMOTES_DIR )
169
- with open (path ) as schema_file :
170
- remotes [relative_path ] = json .load (schema_file )
183
+ remotes [relative_path ] = json .loads (path .read_text ())
171
184
json .dump (remotes , sys .stdout , indent = 4 , sort_keys = True )
172
185
elif arguments .command == "dump_remotes" :
173
186
if arguments .update :
174
187
shutil .rmtree (arguments .out_dir , ignore_errors = True )
175
188
176
189
try :
177
190
shutil .copytree (REMOTES_DIR , arguments .out_dir )
178
- except OSError as e :
179
- if e .errno == errno .EEXIST :
180
- print ("%s already exists. Aborting." % arguments .out_dir )
181
- sys .exit (1 )
182
- raise
191
+ except FileExistsError :
192
+ print (f"{ arguments .out_dir } already exists. Aborting." )
193
+ sys .exit (1 )
183
194
elif arguments .command == "serve" :
184
195
try :
185
196
import flask
0 commit comments