4040 option_github_repository ,
4141 option_image_name ,
4242 option_image_tag_for_running ,
43+ option_include_success_outputs ,
4344 option_integration ,
4445 option_mount_sources ,
4546 option_mssql_version ,
4647 option_mysql_version ,
48+ option_parallelism ,
4749 option_postgres_version ,
4850 option_python ,
51+ option_run_parallel_test ,
52+ option_skip_cleanup ,
4953 option_verbose ,
5054)
5155from airflow_breeze .utils .console import get_console , message_type_from_return_code
5559 get_env_variables_for_docker_commands ,
5660 perform_environment_checks ,
5761)
62+ from airflow_breeze .utils .parallel import check_async_run_results , run_with_pool
5863from airflow_breeze .utils .run_tests import run_docker_compose_tests
5964from airflow_breeze .utils .run_utils import RunCommandResult , run_command
6065
@@ -189,6 +194,68 @@ def run_with_progress(
189194 return result
190195
191196
197+ def run_tests (
198+ env_variables : Dict [str , str ], dry_run : bool , verbose : bool , test_type : str , extra_pytest_args : Tuple
199+ ) -> Tuple [int , str ]:
200+ env_variables ['TEST_TYPE' ] = test_type
201+ perform_environment_checks (verbose = verbose )
202+ cmd = ['docker-compose' , 'run' , '--service-ports' , '--rm' , 'airflow' ]
203+ cmd .extend (list (extra_pytest_args ))
204+ test_result = run_command (
205+ cmd ,
206+ verbose = verbose ,
207+ dry_run = dry_run ,
208+ env = env_variables ,
209+ )
210+ return (
211+ test_result .returncode ,
212+ f"Running tests { test_type } " ,
213+ )
214+
215+
216+ def run_tests_in_parallel (
217+ env_variables : Dict [str , str ],
218+ test_type_list : List [str ],
219+ include_success_outputs : bool ,
220+ skip_cleanup : bool ,
221+ parallelism : int ,
222+ dry_run : bool ,
223+ verbose : bool ,
224+ extra_pytest_args : Tuple ,
225+ ):
226+ """Run tests in parallel"""
227+ with ci_group (f"Running tests for the type { test_type_list } " ):
228+ # get_console().print(
229+ # f"\n[info]Running tests with parallelism = {parallelism} "
230+ # f"for the test type: {test_type_list}[/]"
231+ # )
232+ all_params = [f"Tests { test_type } " for test_type in test_type_list ]
233+ with run_with_pool (
234+ parallelism = parallelism ,
235+ all_params = all_params ,
236+ ) as (pool , outputs ):
237+ results = [
238+ pool .apply_async (
239+ run_tests ,
240+ kwds = {
241+ "env_variables" : env_variables ,
242+ "dry_run" : dry_run ,
243+ "verbose" : verbose ,
244+ "test_type" : test_type ,
245+ "extra_pytest_args" : extra_pytest_args ,
246+ },
247+ )
248+ for test_type in test_type_list
249+ ]
250+ check_async_run_results (
251+ results = results ,
252+ success = "All tests run correctly" ,
253+ outputs = outputs ,
254+ include_success_outputs = include_success_outputs ,
255+ skip_cleanup = skip_cleanup ,
256+ )
257+
258+
192259@testing .command (
193260 name = 'tests' ,
194261 help = "Run the specified unit test targets." ,
@@ -218,6 +285,7 @@ def run_with_progress(
218285 "tests should be run - for example --test-type \" Providers[airbyte,http]\" " ,
219286 default = "All" ,
220287 type = NotVerifiedBetterChoice (ALLOWED_TEST_TYPE_CHOICES ),
288+ envvar = 'TEST_TYPES' ,
221289)
222290@click .option (
223291 "--test-timeout" ,
@@ -226,6 +294,10 @@ def run_with_progress(
226294 show_default = True ,
227295)
228296@option_db_reset
297+ @option_run_parallel_test
298+ @option_parallelism
299+ @option_include_success_outputs
300+ @option_skip_cleanup
229301@click .argument ('extra_pytest_args' , nargs = - 1 , type = click .UNPROCESSED )
230302def tests (
231303 dry_run : bool ,
@@ -241,8 +313,12 @@ def tests(
241313 test_type : str ,
242314 test_timeout : str ,
243315 db_reset : bool ,
244- image_tag : str | None ,
316+ run_parallel_test : bool ,
317+ parallelism : int ,
318+ image_tag : Optional [str ],
245319 mount_sources : str ,
320+ skip_cleanup : bool ,
321+ include_success_outputs : bool ,
246322):
247323 exec_shell_params = ShellParams (
248324 verbose = verbose ,
@@ -257,10 +333,11 @@ def tests(
257333 )
258334 env_variables = get_env_variables_for_docker_commands (exec_shell_params )
259335 env_variables ['RUN_TESTS' ] = "true"
260- env_variables ["TEST_TYPE" ] = test_type
261- if "[" in test_type and not test_type .startswith ("Providers" ):
262- get_console ().print ("[error]Only 'Providers' test type can specify actual tests with \\ [\\ ][/]" )
263- sys .exit (1 )
336+ if test_type :
337+ env_variables ["TEST_TYPE" ] = test_type
338+ if "[" in test_type and not test_type .startswith ("Providers" ):
339+ get_console ().print ("[error]Only 'Providers' test type can specify actual tests with \\ [\\ ][/]" )
340+ sys .exit (1 )
264341 if test_timeout :
265342 env_variables ["TEST_TIMEOUT" ] = test_timeout
266343 if integration :
@@ -292,6 +369,17 @@ def tests(
292369 verbose = verbose ,
293370 dry_run = dry_run ,
294371 )
372+ elif run_parallel_test :
373+ run_tests_in_parallel (
374+ env_variables = env_variables ,
375+ test_type_list = ALLOWED_TEST_TYPE_CHOICES ,
376+ include_success_outputs = include_success_outputs ,
377+ skip_cleanup = skip_cleanup ,
378+ parallelism = parallelism ,
379+ dry_run = dry_run ,
380+ verbose = verbose ,
381+ extra_pytest_args = extra_pytest_args if extra_pytest_args is not None else (),
382+ )
295383 else :
296384 result = run_command (cmd , verbose = verbose , dry_run = dry_run , env = env_variables , check = False )
297385 sys .exit (result .returncode )
0 commit comments