diff --git a/spectacles/client.py b/spectacles/client.py index 410e4c92..f7e324c2 100644 --- a/spectacles/client.py +++ b/spectacles/client.py @@ -460,7 +460,9 @@ def all_lookml_tests(self, project: str) -> List[JsonDict]: return response.json() - def run_lookml_test(self, project: str, model: str = None) -> List[JsonDict]: + def run_lookml_test( + self, project: str, model: str = None, test: str = None + ) -> List[JsonDict]: """Runs all LookML/data tests for a given project and model (optional) This command only runs tests in production, as the Looker API doesn't currently @@ -474,14 +476,25 @@ def run_lookml_test(self, project: str, model: str = None) -> List[JsonDict]: List[JsonDict]: JSON response containing any LookML/data test errors """ - logger.debug(f"Running LookML tests for project {project}") + if model is None and test is None: + logger.debug(f"Running all LookML tests for project '{project}'") + elif model is None and test is not None: + logger.debug(f"Running LookML test '{test}'") + elif model is not None and test is None: + logger.debug(f"Running all LookML tests for model '{model}'") + elif model is not None and test is not None: + logger.debug(f"Running LookML test '{test}' in model '{model}'") + url = utils.compose_url( self.api_url, path=["projects", project, "lookml_tests", "run"] ) + + params = {} if model is not None: - response = self.get(url=url, params={"model": model}, timeout=TIMEOUT_SEC) - else: - response = self.get(url=url, timeout=TIMEOUT_SEC) + params["model"] = model + if test is not None: + params["test"] = test + response = self.session.get(url=url, params=params, timeout=TIMEOUT_SEC) try: response.raise_for_status() diff --git a/spectacles/validators.py b/spectacles/validators.py index 4b4002b8..bf567144 100644 --- a/spectacles/validators.py +++ b/spectacles/validators.py @@ -85,20 +85,34 @@ def validate( if exclusions is None: exclusions = [] - tests = self.client.all_lookml_tests(self.project) - - # The error objects don't contain the name of the explore - # We create this mapping to help look up the explore from the test name (unique) - test_to_explore = {test["name"]: test["explore_name"] for test in tests} - - test_count = len(tests) + all_tests = self.client.all_lookml_tests(self.project) + selected_tests = [] + test_to_explore = {} + for test in all_tests: + if is_selected( + test["model_name"], test["explore_name"], selectors, exclusions + ): + selected_tests.append(test) + # The error objects don't contain the name of the explore + # We create this mapping to help look up the explore from the test name + test_to_explore[test["name"]] = test["explore_name"] + + test_count = len(selected_tests) printer.print_header( f"Running {test_count} {'test' if test_count == 1 else 'tests'}" ) + test_results: List[Dict[str, Any]] = [] + for test in selected_tests: + test_name = test["name"] + model_name = test["model_name"] + results = self.client.run_lookml_test( + self.project, model=model_name, test=test_name + ) + test_results.extend(results) + tested = [] errors = [] - test_results = self.client.run_lookml_test(self.project) for result in test_results: explore = test_to_explore[result["test_name"]]