diff --git a/.buildkite/autogenerate_pipeline.py b/.buildkite/autogenerate_pipeline.py index 83fe5b1..50216a0 100755 --- a/.buildkite/autogenerate_pipeline.py +++ b/.buildkite/autogenerate_pipeline.py @@ -64,11 +64,11 @@ CONTAINER_VERSION = "v24" # This represents the version of the Buildkite Docker plugin. DOCKER_PLUGIN_VERSION = "v5.3.0" -X86_AGENT_TAGS = os.getenv('X86_LINUX_AGENT_TAGS') -AARCH64_AGENT_TAGS = os.getenv('AARCH64_LINUX_AGENT_TAGS') -DOCKER_PLUGIN_CONFIG = os.getenv('DOCKER_PLUGIN_CONFIG') -TESTS_TO_SKIP = os.getenv('TESTS_TO_SKIP') -TIMEOUTS_MIN = os.getenv('TIMEOUTS_MIN') +X86_AGENT_TAGS = os.getenv("X86_LINUX_AGENT_TAGS") +AARCH64_AGENT_TAGS = os.getenv("AARCH64_LINUX_AGENT_TAGS") +DOCKER_PLUGIN_CONFIG = os.getenv("DOCKER_PLUGIN_CONFIG") +TESTS_TO_SKIP = os.getenv("TESTS_TO_SKIP") +TIMEOUTS_MIN = os.getenv("TIMEOUTS_MIN") # This env allows setting the hypervisor on which the tests are running at the # pipeline level. This will not override the hypervisor tag in case one is # already specified in the test definition. @@ -76,7 +76,7 @@ TIMEOUTS_MIN = os.getenv('TIMEOUTS_MIN') # experiencing some timeouts mostly with the mshv hosts right now, and we are # fixing the default to kvm to work around that problem. # More details here: https://github.com/rust-vmm/community/issues/137 -DEFAULT_AGENT_TAG_HYPERVISOR = os.getenv('DEFAULT_AGENT_TAG_HYPERVISOR', 'kvm') +DEFAULT_AGENT_TAG_HYPERVISOR = os.getenv("DEFAULT_AGENT_TAG_HYPERVISOR", "kvm") PARENT_DIR = pathlib.Path(__file__).parent.resolve() @@ -99,59 +99,59 @@ class BuildkiteStep: # dictionaries are ordered. For readability reasons, this order should # not be changed. self.step_config = { - 'label': None, - 'command': None, - 'retry': {'automatic': False}, - 'agents': {'os': 'linux'}, - 'plugins': [ + "label": None, + "command": None, + "retry": {"automatic": False}, + "agents": {"os": "linux"}, + "plugins": [ { f"docker#{DOCKER_PLUGIN_VERSION}": { - 'image': f"rustvmm/dev:{CONTAINER_VERSION}", - 'always-pull': True + "image": f"rustvmm/dev:{CONTAINER_VERSION}", + "always-pull": True, } } ], - 'timeout_in_minutes': 15 + "timeout_in_minutes": 15, } def _set_platform(self, platform): - """ Set platform if given in the json input. """ + """Set platform if given in the json input.""" if platform: # We need to change `aarch64` to `arm` because of the way we are # setting the tags on the host. - if platform == 'aarch64': - platform = 'arm' - self.step_config['agents']['platform'] = f"{platform}.metal" + if platform == "aarch64": + platform = "arm" + self.step_config["agents"]["platform"] = f"{platform}.metal" def _set_hypervisor(self, hypervisor): - """ Set hypervisor if given in the json input. """ - supported_hypervisors = ['kvm', 'mshv'] + """Set hypervisor if given in the json input.""" + supported_hypervisors = ["kvm", "mshv"] if hypervisor: if hypervisor in supported_hypervisors: - self.step_config['agents']['hypervisor'] = hypervisor + self.step_config["agents"]["hypervisor"] = hypervisor def _set_conditional(self, conditional): - """ Set conditional if given in the json input. """ + """Set conditional if given in the json input.""" if conditional: - self.step_config['if'] = conditional + self.step_config["if"] = conditional def _set_timeout_in_minutes(self, timeout): - """ Set the timeout if given in the json input. """ + """Set the timeout if given in the json input.""" if timeout: - self.step_config['timeout_in_minutes'] = timeout + self.step_config["timeout_in_minutes"] = timeout def _set_agent_queue(self, queue): """Set the agent queue if provided in the json input.""" if queue: - self.step_config['agents']['queue'] = queue + self.step_config["agents"]["queue"] = queue def _add_docker_config(self, cfg): - """ Add configuration for docker if given in the json input. """ + """Add configuration for docker if given in the json input.""" if cfg: - target = self.step_config['plugins'][0][f"docker#{DOCKER_PLUGIN_VERSION}"] + target = self.step_config["plugins"][0][f"docker#{DOCKER_PLUGIN_VERSION}"] for key, val in cfg.items(): target[key] = val @@ -164,13 +164,11 @@ class BuildkiteStep: if env_var: env_cfg = json.loads(env_var) - tests = env_cfg.get('tests') - assert tests, \ - f"Environment variable {env_var} is missing the `tests` key." + tests = env_cfg.get("tests") + assert tests, f"Environment variable {env_var} is missing the `tests` key." - cfg = env_cfg.get('cfg') - assert cfg, \ - f"Environment variable {env_var} is missing the `cfg` key." + cfg = env_cfg.get("cfg") + assert cfg, f"Environment variable {env_var} is missing the `cfg` key." if test_name in tests: if override: @@ -186,17 +184,17 @@ class BuildkiteStep: """ env_var = None - platform = self.step_config['agents'].get('platform') + platform = self.step_config["agents"].get("platform") # Since the platform is optional, only override the config if the # platform was provided. if platform: - if platform == 'x86_64.metal' and X86_AGENT_TAGS: + if platform == "x86_64.metal" and X86_AGENT_TAGS: env_var = X86_AGENT_TAGS - if platform == 'arm.metal' and AARCH64_AGENT_TAGS: + if platform == "arm.metal" and AARCH64_AGENT_TAGS: env_var = AARCH64_AGENT_TAGS - target = self.step_config['agents'] + target = self.step_config["agents"] self._env_change_config(test_name, env_var, target, override=True) def _env_add_docker_config(self, test_name): @@ -205,7 +203,7 @@ class BuildkiteStep: `DOCKER_PLUGIN_CONFIG` environment variable. """ - target = self.step_config['plugins'][0][f"docker#{DOCKER_PLUGIN_VERSION}"] + target = self.step_config["plugins"][0][f"docker#{DOCKER_PLUGIN_VERSION}"] self._env_change_config(test_name, DOCKER_PLUGIN_CONFIG, target) def _env_override_timeout(self, test_name): @@ -221,28 +219,25 @@ class BuildkiteStep: Further configuration from environment variables may be added. """ - test_name = input.get('test_name') - command = input.get('command') - platform = input.get('platform') - hypervisor = input.get('hypervisor') - docker = input.get('docker_plugin') - conditional = input.get('conditional') - timeout = input.get('timeout_in_minutes') - queue = input.get('queue') + test_name = input.get("test_name") + command = input.get("command") + platform = input.get("platform") + hypervisor = input.get("hypervisor") + docker = input.get("docker_plugin") + conditional = input.get("conditional") + timeout = input.get("timeout_in_minutes") + queue = input.get("queue") # Mandatory keys. assert test_name, "Step is missing test name." platform_string = f"-{platform}" if platform else "" - self.step_config['label'] = f"{test_name}{platform_string}" + self.step_config["label"] = f"{test_name}{platform_string}" assert command, "Step is missing command." if "{target_platform}" in command: - assert platform, \ - "Command requires platform, but platform is missing." - command = command.replace( - "{target_platform}", platform - ) - self.step_config['command'] = command + assert platform, "Command requires platform, but platform is missing." + command = command.replace("{target_platform}", platform) + self.step_config["command"] = command # Optional keys. self._set_platform(platform) @@ -262,9 +257,19 @@ class BuildkiteStep: # forwarding the key, values without any change. # We need to filter for keys that have special meaning and which we # don't want to re-add. - special_keys = ['conditional', 'docker_plugin', 'platform', 'test_name', 'queue', 'hypervisor'] - additional_keys = {k: v for k, v in input.items() if not (k in self.step_config) and - not(k in special_keys)} + special_keys = [ + "conditional", + "docker_plugin", + "platform", + "test_name", + "queue", + "hypervisor", + ] + additional_keys = { + k: v + for k, v in input.items() + if not (k in self.step_config) and not (k in special_keys) + } if additional_keys: self.step_config.update(additional_keys) @@ -283,15 +288,15 @@ class BuildkiteConfig: self.bk_config = None def build(self, input): - """ Build the final Buildkite configuration fron the json input. """ + """Build the final Buildkite configuration fron the json input.""" - self.bk_config = {'steps': []} - tests = input.get('tests') + self.bk_config = {"steps": []} + tests = input.get("tests") assert tests, "Input is missing list of tests." for test in tests: - platforms = test.get('platform') - test_name = test.get('test_name') + platforms = test.get("platform") + test_name = test.get("test_name") if TESTS_TO_SKIP: tests_to_skip = json.loads(TESTS_TO_SKIP) @@ -305,20 +310,20 @@ class BuildkiteConfig: for platform in platforms: step_input = copy.deepcopy(test) - step_input['platform'] = platform - if not step_input.get('hypervisor'): - step_input['hypervisor'] = DEFAULT_AGENT_TAG_HYPERVISOR + step_input["platform"] = platform + if not step_input.get("hypervisor"): + step_input["hypervisor"] = DEFAULT_AGENT_TAG_HYPERVISOR step = BuildkiteStep() step_output = step.build(step_input) - self.bk_config['steps'].append(step_output) + self.bk_config["steps"].append(step_output) # Return the object's attributes and their values as a dictionary. return self.bk_config def generate_pipeline(config_file): - """ Generate the pipeline yaml file from a json configuration file. """ + """Generate the pipeline yaml file from a json configuration file.""" with open(config_file) as json_file: json_cfg = json.load(json_file) @@ -329,7 +334,7 @@ def generate_pipeline(config_file): yaml.dump(output, sys.stdout, sort_keys=False) -if __name__ == '__main__': +if __name__ == "__main__": help_text = dedent( """ This script supports overriding the following configurations through @@ -345,17 +350,18 @@ if __name__ == '__main__': - TIMEOUTS_MIN: overrides the timeout value for specific tests. """ ) - parser = ArgumentParser(description=help_text, - formatter_class=RawTextHelpFormatter) + parser = ArgumentParser(description=help_text, formatter_class=RawTextHelpFormatter) # By default we're generating the rust-vmm-ci pipeline with the test # configuration committed to this repository. # This parameter is useful for generating the pipeline for repositories # that have custom pipelines, and it helps with keeping the container # version the same across pipelines. - parser.add_argument('-t', '--test-description', - metavar="JSON_FILE", - help='The path to the JSON file containing the test' - ' description for the CI.', - default=f'{PARENT_DIR}/test_description.json') + parser.add_argument( + "-t", + "--test-description", + metavar="JSON_FILE", + help="The path to the JSON file containing the test" " description for the CI.", + default=f"{PARENT_DIR}/test_description.json", + ) args = parser.parse_args() generate_pipeline(args.test_description) diff --git a/.github/workflows/black.yaml b/.github/workflows/black.yaml new file mode 100644 index 0000000..0aaee32 --- /dev/null +++ b/.github/workflows/black.yaml @@ -0,0 +1,14 @@ +on: + push: + +jobs: + black: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Install black + run: pip install black + + - name: Run black + run: black . --check \ No newline at end of file diff --git a/integration_tests/conftest.py b/integration_tests/conftest.py index 72dfe3f..32f7180 100644 --- a/integration_tests/conftest.py +++ b/integration_tests/conftest.py @@ -15,28 +15,22 @@ def pytest_addoption(parser): "--profile", default=PROFILE_CI, choices=[PROFILE_CI, PROFILE_DEVEL], - help="Profile for running the test: {} or {}".format( - PROFILE_CI, - PROFILE_DEVEL - ) + help="Profile for running the test: {} or {}".format(PROFILE_CI, PROFILE_DEVEL), ) parser.addoption( "--no-cleanup", action="store_true", default=False, help="Keep the coverage report in `kcov_output` directory. If this " - "flag is not provided, both coverage related directories are " - "removed." + "flag is not provided, both coverage related directories are " + "removed.", ) parser.addoption( "--test-scope", default=WORKSPACE, choices=[WORKSPACE, CRATE], - help="Defines the scope of running tests: {} or {}".format( - WORKSPACE, - CRATE - ) + help="Defines the scope of running tests: {} or {}".format(WORKSPACE, CRATE), ) diff --git a/integration_tests/test_benchmark.py b/integration_tests/test_benchmark.py index 4fe0fd6..6b86de3 100644 --- a/integration_tests/test_benchmark.py +++ b/integration_tests/test_benchmark.py @@ -14,14 +14,12 @@ import subprocess from utils import get_repo_root_path -REMOTE = \ - os.environ.get('BUILDKITE_REPO') or \ - os.environ.get('REMOTE') or \ - "origin" -BASE_BRANCH = \ - os.environ.get('BUILDKITE_PULL_REQUEST_BASE_BRANCH') or \ - os.environ.get('BASE_BRANCH') or \ - "main" +REMOTE = os.environ.get("BUILDKITE_REPO") or os.environ.get("REMOTE") or "origin" +BASE_BRANCH = ( + os.environ.get("BUILDKITE_PULL_REQUEST_BASE_BRANCH") + or os.environ.get("BASE_BRANCH") + or "main" +) # File used for saving the results of cargo bench # when running on the PR branch. PR_BENCH_RESULTS_FILE = "pr_bench_results" @@ -67,12 +65,9 @@ def test_bench(): # This is a bit of a &*%^ way of checking if the benchmark does not # exist. Hopefully it will be possible to check it in another way # ...soon - print( - "There are no benchmarks in main. No comparison can happen." - ) + print("There are no benchmarks in main. No comparison can happen.") else: - assert return_code == 0, "stdout: {}\n stderr: {}".format( - stdout, stderr) + assert return_code == 0, "stdout: {}\n stderr: {}".format(stdout, stderr) def _run_cargo_bench(baseline): @@ -80,43 +75,44 @@ def _run_cargo_bench(baseline): process = subprocess.run( "cargo bench --bench main --all-features -- --noplot " "--save-baseline {}".format(baseline), - shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE + shell=True, + stderr=subprocess.PIPE, + stdout=subprocess.PIPE, ) - return process.returncode, process.stdout.decode('utf-8'),\ - process.stderr.decode('utf-8') + return ( + process.returncode, + process.stdout.decode("utf-8"), + process.stderr.decode("utf-8"), + ) def _run_critcmp(): p = subprocess.run( - "critcmp {} {}".format( - UPSTREAM_BENCH_RESULTS_FILE, PR_BENCH_RESULTS_FILE - ), - shell=True, check=True, + "critcmp {} {}".format(UPSTREAM_BENCH_RESULTS_FILE, PR_BENCH_RESULTS_FILE), + shell=True, + check=True, stdout=subprocess.PIPE, - stderr=subprocess.PIPE + stderr=subprocess.PIPE, ) - print(p.stdout.decode('utf-8')) - print('ERRORS') - print(p.stderr.decode('utf-8')) + print(p.stdout.decode("utf-8")) + print("ERRORS") + print(p.stderr.decode("utf-8")) def _git_checkout_upstream_branch(): subprocess.run( - "git fetch {} {}".format(REMOTE, BASE_BRANCH), - shell=True, check=True - ) - subprocess.run( - "git checkout FETCH_HEAD", - shell=True, check=True + "git fetch {} {}".format(REMOTE, BASE_BRANCH), shell=True, check=True ) + subprocess.run("git checkout FETCH_HEAD", shell=True, check=True) def _git_checkout_pr_branch(): subprocess.run( "git checkout -", - shell=True, check=True, + shell=True, + check=True, stdout=subprocess.PIPE, - stderr=subprocess.PIPE + stderr=subprocess.PIPE, ) diff --git a/integration_tests/test_commit_format.py b/integration_tests/test_commit_format.py index 5f789ba..f815231 100644 --- a/integration_tests/test_commit_format.py +++ b/integration_tests/test_commit_format.py @@ -16,14 +16,12 @@ from utils import get_cmd_output COMMIT_TITLE_MAX_LEN = 60 COMMIT_BODY_LINE_MAX_LEN = 75 -REMOTE = \ - os.environ.get('BUILDKITE_REPO') or \ - os.environ.get('REMOTE') or \ - "origin" -BASE_BRANCH = \ - os.environ.get('BUILDKITE_PULL_REQUEST_BASE_BRANCH') or \ - os.environ.get('BASE_BRANCH') or \ - "main" +REMOTE = os.environ.get("BUILDKITE_REPO") or os.environ.get("REMOTE") or "origin" +BASE_BRANCH = ( + os.environ.get("BUILDKITE_PULL_REQUEST_BASE_BRANCH") + or os.environ.get("BASE_BRANCH") + or "main" +) def test_commit_format(): @@ -50,8 +48,7 @@ def test_commit_format(): ) from None # Get hashes of PR's commits in their abbreviated form for # a prettier printing. - shas_cmd = "git log --no-merges --pretty=%h --no-decorate " \ - "FETCH_HEAD..HEAD" + shas_cmd = "git log --no-merges --pretty=%h --no-decorate " "FETCH_HEAD..HEAD" shas = get_cmd_output(shas_cmd) for sha in shas.split(): @@ -63,18 +60,20 @@ def test_commit_format(): message_cmd = "git show --pretty=format:%B -s " + sha message = get_cmd_output(message_cmd) message_lines = message.split("\n") - assert len(message_lines) >= 3,\ - "The commit '{}' should contain at least 3 lines: title, " \ - "blank line and a sign-off one." \ - .format(sha) + assert len(message_lines) >= 3, ( + "The commit '{}' should contain at least 3 lines: title, " + "blank line and a sign-off one.".format(sha) + ) title = message_lines[0] - assert message_lines[1] == "",\ - "For commit '{}', title is divided into multiple lines. " \ - "Please keep it one line long and make sure you add a blank " \ + assert message_lines[1] == "", ( + "For commit '{}', title is divided into multiple lines. " + "Please keep it one line long and make sure you add a blank " "line between title and description.".format(sha) - assert len(title) <= COMMIT_TITLE_MAX_LEN,\ - "For commit '{}', title exceeds {} chars. " \ + ) + assert len(title) <= COMMIT_TITLE_MAX_LEN, ( + "For commit '{}', title exceeds {} chars. " "Please keep it shorter.".format(sha, COMMIT_TITLE_MAX_LEN) + ) found_signed_off = False @@ -85,11 +84,13 @@ def test_commit_format(): # the commit message ended and we don't want to check # line lengths anymore for the current commit. break - assert len(line) <= COMMIT_BODY_LINE_MAX_LEN,\ - "For commit '{}', message line '{}' exceeds {} chars. " \ - "Please keep it shorter or split it in " \ - "multiple lines.".format(sha, line, - COMMIT_BODY_LINE_MAX_LEN) - assert found_signed_off, "Commit '{}' is not signed. " \ - "Please run 'git commit -s --amend' " \ - "on it.".format(sha) + assert len(line) <= COMMIT_BODY_LINE_MAX_LEN, ( + "For commit '{}', message line '{}' exceeds {} chars. " + "Please keep it shorter or split it in " + "multiple lines.".format(sha, line, COMMIT_BODY_LINE_MAX_LEN) + ) + assert found_signed_off, ( + "Commit '{}' is not signed. " + "Please run 'git commit -s --amend' " + "on it.".format(sha) + ) diff --git a/integration_tests/test_coverage.py b/integration_tests/test_coverage.py index 252809e..58560df 100644 --- a/integration_tests/test_coverage.py +++ b/integration_tests/test_coverage.py @@ -51,15 +51,16 @@ def _read_test_config(): assert "exclude_path" in coverage_config assert "crate_features" in coverage_config - assert ' ' not in coverage_config["crate_features"], \ - "spaces are not allowed in crate_features value" + assert ( + " " not in coverage_config["crate_features"] + ), "spaces are not allowed in crate_features value" return coverage_config def _write_coverage_config(coverage_config): """Updates the coverage config file as per `coverage_config`""" - with open(COVERAGE_CONFIG_PATH, 'w') as outfile: + with open(COVERAGE_CONFIG_PATH, "w") as outfile: json.dump(coverage_config, outfile) @@ -78,48 +79,43 @@ def _get_current_coverage(coverage_config, no_cleanup, test_scope): shutil.rmtree(kcov_output_dir, ignore_errors=True) shutil.rmtree(kcov_build_dir, ignore_errors=True) - exclude_pattern = ( - '${CARGO_HOME:-$HOME/.cargo/},' - 'usr/lib/,' - 'lib/' - ) + exclude_pattern = "${CARGO_HOME:-$HOME/.cargo/}," "usr/lib/," "lib/" exclude_region = "'mod tests {'" additional_exclude_path = coverage_config["exclude_path"] if additional_exclude_path: - exclude_pattern += ',' + additional_exclude_path + exclude_pattern += "," + additional_exclude_path - additional_kcov_param = '' + additional_kcov_param = "" if test_scope == pytest.workspace: - additional_kcov_param += '--all ' + additional_kcov_param += "--all " crate_features = coverage_config["crate_features"] if crate_features: - additional_kcov_param += '--features=' + crate_features + additional_kcov_param += "--features=" + crate_features - kcov_cmd = "CARGO_TARGET_DIR={} cargo kcov {} " \ - "--output {} -- " \ - "--exclude-region={} " \ - "--exclude-pattern={} " \ - "--verify".format( - kcov_build_dir, - additional_kcov_param, - kcov_output_dir, - exclude_region, - exclude_pattern - ) + kcov_cmd = ( + "CARGO_TARGET_DIR={} cargo kcov {} " + "--output {} -- " + "--exclude-region={} " + "--exclude-pattern={} " + "--verify".format( + kcov_build_dir, + additional_kcov_param, + kcov_output_dir, + exclude_region, + exclude_pattern, + ) + ) # Pytest closes stdin by default, but some tests might need it to be open. # In the future, should the need arise, we can feed custom data to stdin. - subprocess.run(kcov_cmd, shell=True, check=True, input=b'') + subprocess.run(kcov_cmd, shell=True, check=True, input=b"") # Read the coverage reported by kcov. - coverage_file = os.path.join(kcov_output_dir, 'index.js') + coverage_file = os.path.join(kcov_output_dir, "index.js") with open(coverage_file) as cov_output: - coverage = float(re.findall( - r'"covered":"(\d+\.\d)"', - cov_output.read() - )[0]) + coverage = float(re.findall(r'"covered":"(\d+\.\d)"', cov_output.read())[0]) # Remove coverage related directories. # If user provided `--no-cleanup` flag, `kcov_output_dir` @@ -140,14 +136,12 @@ def test_coverage(profile, no_cleanup, test_scope): if previous_coverage < current_coverage: if profile == pytest.profile_ci: # In the CI Profile we expect the coverage to be manually updated. - assert False, \ - "Coverage is increased from {} to {}. " \ - "Please update the coverage in coverage_config_{}.json."\ - .format( - previous_coverage, - current_coverage, - platform.machine() + assert False, ( + "Coverage is increased from {} to {}. " + "Please update the coverage in coverage_config_{}.json.".format( + previous_coverage, current_coverage, platform.machine() ) + ) elif profile == pytest.profile_devel: coverage_config["coverage_score"] = current_coverage _write_coverage_config(coverage_config) @@ -157,5 +151,7 @@ def test_coverage(profile, no_cleanup, test_scope): # `pytest_addoption`. assert False, "Invalid test profile." elif previous_coverage > current_coverage: - assert False, "Coverage drops by {:.2f}%. Please add unit tests for " \ - "the uncovered lines.".format(diff) + assert False, ( + "Coverage drops by {:.2f}%. Please add unit tests for " + "the uncovered lines.".format(diff) + ) diff --git a/integration_tests/utils.py b/integration_tests/utils.py index 85043c2..80269c3 100644 --- a/integration_tests/utils.py +++ b/integration_tests/utils.py @@ -15,7 +15,6 @@ def get_repo_root_path(): def get_cmd_output(cmd): """Returns stdout content of `cmd` command.""" - cmd_out = subprocess.run(cmd, shell=True, check=True, - stdout=subprocess.PIPE) - stdout = cmd_out.stdout.decode('utf-8') + cmd_out = subprocess.run(cmd, shell=True, check=True, stdout=subprocess.PIPE) + stdout = cmd_out.stdout.decode("utf-8") return stdout diff --git a/test_run.py b/test_run.py index bd7eb64..86a8810 100755 --- a/test_run.py +++ b/test_run.py @@ -21,19 +21,18 @@ class TestsContainer(unittest.TestCase): def make_test_function(command): def test(self): subprocess.run(command, shell=True, check=True) + return test -def retrieve_test_list( - config_file=f"{PARENT_DIR}/.buildkite/test_description.json" -): +def retrieve_test_list(config_file=f"{PARENT_DIR}/.buildkite/test_description.json"): with open(config_file) as jsonFile: test_list = json.load(jsonFile) jsonFile.close() return test_list -if __name__ == '__main__': +if __name__ == "__main__": help_text = dedent( """ This script allows running all the tests at once on the local machine. @@ -44,15 +43,14 @@ if __name__ == '__main__': base branch, and these tests may not work as expected. """ ) - parser = ArgumentParser(description=help_text, - formatter_class=RawTextHelpFormatter) + parser = ArgumentParser(description=help_text, formatter_class=RawTextHelpFormatter) parser.parse_args() test_config = retrieve_test_list() - for test in test_config['tests']: - command = test['command'] + for test in test_config["tests"]: + command = test["command"] command = command.replace("{target_platform}", platform.machine()) test_func = make_test_function(command) - setattr(TestsContainer, 'test_{}'.format(test['test_name']), test_func) + setattr(TestsContainer, "test_{}".format(test["test_name"]), test_func) unittest.main(verbosity=2)