13
13
# limitations under the License.
14
14
15
15
from __future__ import absolute_import
16
+ from concurrent .futures import ThreadPoolExecutor
16
17
from pathlib import Path
17
18
import os
18
19
import sys
29
30
ADS_TEMPLATES = path .join (path .dirname (__file__ ), "gapic" , "ads-templates" )
30
31
31
32
32
- @nox .session (python = ["3.6" , "3.7" , "3.8" , "3.9" , "3.10" ])
33
+ ALL_PYTHON = (
34
+ "3.6" ,
35
+ "3.7" ,
36
+ "3.8" ,
37
+ "3.9" ,
38
+ )
39
+
40
+ NEWEST_PYTHON = "3.9"
41
+
42
+
43
+ @nox .session (python = ALL_PYTHON )
33
44
def unit (session ):
34
45
"""Run the unit test suite."""
35
46
@@ -50,11 +61,89 @@ def unit(session):
50
61
"--cov-report=term" ,
51
62
"--cov-fail-under=100" ,
52
63
path .join ("tests" , "unit" ),
53
- ]
64
+ ]
54
65
),
55
66
)
56
67
57
68
69
+ FRAG_DIR = Path ("tests" ) / "fragments"
70
+ FRAGMENT_FILES = tuple (
71
+ Path (dirname ).relative_to (FRAG_DIR ) / f
72
+ for dirname , _ , files in os .walk (FRAG_DIR )
73
+ for f in files
74
+ if os .path .splitext (f )[1 ] == ".proto" and f .startswith ("test_" )
75
+ )
76
+
77
+ # Note: this class lives outside 'fragment'
78
+ # so that, if necessary, it can be pickled for a ProcessPoolExecutor
79
+ # A callable class is necessary so that the session can be closed over
80
+ # instead of passed in, which simplifies the invocation via map.
81
+ class FragTester :
82
+ def __init__ (self , session ):
83
+ self .session = session
84
+
85
+ def __call__ (self , frag ):
86
+ with tempfile .TemporaryDirectory () as tmp_dir :
87
+ # Generate the fragment GAPIC.
88
+ outputs = []
89
+ outputs .append (
90
+ self .session .run (
91
+ "python" ,
92
+ "-m" ,
93
+ "grpc_tools.protoc" ,
94
+ f"--proto_path={ str (FRAG_DIR )} " ,
95
+ f"--python_gapic_out={ tmp_dir } " ,
96
+ "--python_gapic_opt=transport=grpc+rest" ,
97
+ str (frag ),
98
+ external = True ,
99
+ silent = True ,
100
+ )
101
+ )
102
+
103
+ # Install the generated fragment library.
104
+ # Note: install into the tempdir to prevent issues
105
+ # with running pip concurrently.
106
+ self .session .install (tmp_dir , "-e" , "." , "-t" , tmp_dir , "-qqq" )
107
+
108
+ # Run the fragment's generated unit tests.
109
+ # Don't bother parallelizing them: we already parallelize
110
+ # the fragments, and there usually aren't too many tests per fragment.
111
+ outputs .append (
112
+ self .session .run (
113
+ "py.test" ,
114
+ "--quiet" ,
115
+ f"--cov-config={ str (Path (tmp_dir ) / '.coveragerc' )} " ,
116
+ "--cov-report=term" ,
117
+ "--cov-fail-under=100" ,
118
+ str (Path (tmp_dir ) / "tests" / "unit" ),
119
+ silent = True ,
120
+ )
121
+ )
122
+
123
+ return "" .join (outputs )
124
+
125
+
126
+ # TODO(dovs): ads templates
127
+ @nox .session (python = ALL_PYTHON )
128
+ def fragment (session ):
129
+ session .install (
130
+ "coverage" ,
131
+ "pytest" ,
132
+ "pytest-cov" ,
133
+ "pytest-xdist" ,
134
+ "asyncmock" ,
135
+ "pytest-asyncio" ,
136
+ "grpcio-tools" ,
137
+ )
138
+ session .install ("-e" , "." )
139
+
140
+ with ThreadPoolExecutor () as p :
141
+ all_outs = p .map (FragTester (session ), FRAGMENT_FILES )
142
+
143
+ output = "" .join (all_outs )
144
+ session .log (output )
145
+
146
+
58
147
# TODO(yon-mg): -add compute context manager that includes rest transport
59
148
# -add compute unit tests
60
149
# (to test against temporarily while rest transport is incomplete)
@@ -114,8 +203,7 @@ def showcase_library(
114
203
f"google/showcase/v1beta1/messaging.proto" ,
115
204
)
116
205
session .run (
117
- * cmd_tup ,
118
- external = True ,
206
+ * cmd_tup , external = True ,
119
207
)
120
208
121
209
# Install the library.
@@ -124,7 +212,7 @@ def showcase_library(
124
212
yield tmp_dir
125
213
126
214
127
- @nox .session (python = "3.9" )
215
+ @nox .session (python = NEWEST_PYTHON )
128
216
def showcase (
129
217
session ,
130
218
templates = "DEFAULT" ,
@@ -136,12 +224,14 @@ def showcase(
136
224
with showcase_library (session , templates = templates , other_opts = other_opts ):
137
225
session .install ("mock" , "pytest" , "pytest-asyncio" )
138
226
session .run (
139
- "py.test" , "--quiet" , * (session .posargs or [path .join ("tests" , "system" )]),
227
+ "py.test" ,
228
+ "--quiet" ,
229
+ * (session .posargs or [path .join ("tests" , "system" )]),
140
230
env = env ,
141
231
)
142
232
143
233
144
- @nox .session (python = "3.9" )
234
+ @nox .session (python = NEWEST_PYTHON )
145
235
def showcase_mtls (
146
236
session ,
147
237
templates = "DEFAULT" ,
@@ -161,7 +251,7 @@ def showcase_mtls(
161
251
)
162
252
163
253
164
- @nox .session (python = "3.9" )
254
+ @nox .session (python = NEWEST_PYTHON )
165
255
def showcase_alternative_templates (session ):
166
256
templates = path .join (path .dirname (__file__ ), "gapic" , "ads-templates" )
167
257
showcase (
@@ -172,7 +262,7 @@ def showcase_alternative_templates(session):
172
262
)
173
263
174
264
175
- @nox .session (python = "3.9" )
265
+ @nox .session (python = NEWEST_PYTHON )
176
266
def showcase_mtls_alternative_templates (session ):
177
267
templates = path .join (path .dirname (__file__ ), "gapic" , "ads-templates" )
178
268
showcase_mtls (
@@ -200,12 +290,12 @@ def run_showcase_unit_tests(session, fail_under=100):
200
290
"--quiet" ,
201
291
"--cov=google" ,
202
292
"--cov-append" ,
203
- f"--cov-fail-under={ str (fail_under )} " ,
293
+ f"--cov-fail-under={ str (fail_under )} " ,
204
294
* (session .posargs or [path .join ("tests" , "unit" )]),
205
295
)
206
296
207
297
208
- @nox .session (python = [ "3.6" , "3.7" , "3.8" , "3.9" ] )
298
+ @nox .session (python = ALL_PYTHON )
209
299
def showcase_unit (
210
300
session , templates = "DEFAULT" , other_opts : typing .Iterable [str ] = (),
211
301
):
@@ -233,14 +323,16 @@ def showcase_unit(
233
323
run_showcase_unit_tests (session , fail_under = 100 )
234
324
235
325
236
- @nox .session (python = [ "3.7" , "3.8" , "3.9" ])
326
+ @nox .session (python = ALL_PYTHON [ 1 :]) # Do not test 3.6
237
327
def showcase_unit_alternative_templates (session ):
238
- with showcase_library (session , templates = ADS_TEMPLATES , other_opts = ("old-naming" ,)) as lib :
328
+ with showcase_library (
329
+ session , templates = ADS_TEMPLATES , other_opts = ("old-naming" ,)
330
+ ) as lib :
239
331
session .chdir (lib )
240
332
run_showcase_unit_tests (session )
241
333
242
334
243
- @nox .session (python = [ "3.9" ] )
335
+ @nox .session (python = NEWEST_PYTHON )
244
336
def showcase_unit_add_iam_methods (session ):
245
337
with showcase_library (session , other_opts = ("add-iam-methods" ,)) as lib :
246
338
session .chdir (lib )
@@ -257,7 +349,7 @@ def showcase_unit_add_iam_methods(session):
257
349
run_showcase_unit_tests (session , fail_under = 100 )
258
350
259
351
260
- @nox .session (python = "3.9" )
352
+ @nox .session (python = NEWEST_PYTHON )
261
353
def showcase_mypy (
262
354
session , templates = "DEFAULT" , other_opts : typing .Iterable [str ] = (),
263
355
):
@@ -273,12 +365,12 @@ def showcase_mypy(
273
365
session .run ("mypy" , "--explicit-package-bases" , "google" )
274
366
275
367
276
- @nox .session (python = "3.9" )
368
+ @nox .session (python = NEWEST_PYTHON )
277
369
def showcase_mypy_alternative_templates (session ):
278
370
showcase_mypy (session , templates = ADS_TEMPLATES , other_opts = ("old-naming" ,))
279
371
280
372
281
- @nox .session (python = "3.9" )
373
+ @nox .session (python = NEWEST_PYTHON )
282
374
def snippetgen (session ):
283
375
# Clone googleapis/api-common-protos which are referenced by the snippet
284
376
# protos
@@ -299,14 +391,10 @@ def snippetgen(session):
299
391
300
392
session .install ("grpcio-tools" , "mock" , "pytest" , "pytest-asyncio" )
301
393
302
- session .run (
303
- "py.test" ,
304
- "-vv" ,
305
- "tests/snippetgen"
306
- )
394
+ session .run ("py.test" , "-vv" , "tests/snippetgen" )
307
395
308
396
309
- @nox .session (python = "3.9" )
397
+ @nox .session (python = NEWEST_PYTHON )
310
398
def docs (session ):
311
399
"""Build the docs."""
312
400
@@ -327,15 +415,10 @@ def docs(session):
327
415
)
328
416
329
417
330
- @nox .session (python = [ "3.7" , "3.8" , "3.9" ] )
418
+ @nox .session (python = NEWEST_PYTHON )
331
419
def mypy (session ):
332
420
"""Perform typecheck analysis."""
333
421
334
- session .install (
335
- "mypy" ,
336
- "types-protobuf" ,
337
- "types-PyYAML" ,
338
- "types-dataclasses"
339
- )
422
+ session .install ("mypy" , "types-protobuf" , "types-PyYAML" , "types-dataclasses" )
340
423
session .install ("." )
341
424
session .run ("mypy" , "gapic" )
0 commit comments