Skip to content

Commit

Permalink
Merge pull request #2572 from mirpedrol/lint-nftest-tags
Browse files Browse the repository at this point in the history
nf-test linting tags
  • Loading branch information
mirpedrol authored Dec 14, 2023
2 parents d1994a7 + 960bff5 commit fcf0c7e
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
- Correctly pass subworkflow linting test if `COMPONENT.out.versions` is used in the script ([#2448](https://github.com/nf-core/tools/pull/2448))
- Check for spaces in modules container URLs ([#2452](https://github.com/nf-core/tools/issues/2452))
- Correctly ignore `timeline.enabled`, `report.enabled`, `trace.enabled`, `dag.enabled` variables when linting a pipeline. ([#2507](https://github.com/nf-core/tools/pull/2507))
- Lint nf-test main.nf.test tags include all used components in chained tests ([#2572](https://github.com/nf-core/tools/pull/2572))
- Don't fail linting if md5sum for empty files are found in a stub test ([#2571](https://github.com/nf-core/tools/pull/2571))

### Modules
Expand Down
44 changes: 44 additions & 0 deletions nf_core/components/nfcore_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,50 @@ def _get_included_components(self, main_nf: Union[Path, str]):
included_components.append(component)
return included_components

def _get_included_components_in_chained_tests(self, main_nf_test: Union[Path, str]):
"""Collect all included components from the main.nf file."""
included_components = []
with open(main_nf_test, "r") as fh:
for line in fh:
if line.strip().startswith("script"):
# get tool/subtool or subworkflow name from script statement, can be:
# if the component is a module TOOL/SUBTOOL:
# '../../SUBTOOL/main.nf'
# '../../../TOOL/SUBTOOL/main.nf'
# '../../../TOOL/main.nf'
# if the component is a module TOOL:
# '../../TOOL/main.nf'
# '../../TOOL/SUBTOOL/main.nf'
# if the component uses full paths or is a subworkflow:
# '(../../)modules/nf-core/TOOL/(SUBTOOL/)main.nf'
# '(../../)subworkflows/nf-core/TOOL/(SUBTOOL/)main.nf'
# the line which uses the current component script:
# '../main.nf'
component = (
line.strip()
.split("../")[-1]
.split(self.org)[-1]
.split("main.nf")[0]
.strip("'")
.strip('"')
.strip("/")
)
if (
"/" in self.component_name
and "/" not in component
and line.count("../") == 2
and self.org not in line
and component != ""
):
# Add the current component name "TOOL" to the tag
component = f"{self.component_name.split('/')[0]}/{component}"
if "subworkflows" in line:
# Add the subworkflows prefix to the tag
component = f"subworkflows/{component}"
if component != "":
included_components.append(component)
return included_components

def get_inputs_from_main_nf(self):
"""Collect all inputs from the main.nf file."""
inputs = []
Expand Down
5 changes: 4 additions & 1 deletion nf_core/modules/lint/module_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,11 @@ def module_tests(_, module: NFCoreComponent):
required_tags = ["modules", "modules_nfcore", module.component_name]
if module.component_name.count("/") == 1:
required_tags.append(module.component_name.split("/")[0])
chained_components_tags = module._get_included_components_in_chained_tests(module.nftest_main_nf)
missing_tags = []
for tag in required_tags:
log.debug(f"Required tags: {required_tags}")
log.debug(f"Included components for chained nf-tests: {chained_components_tags}")
for tag in set(required_tags + chained_components_tags):
if tag not in main_nf_tags:
missing_tags.append(tag)
if len(missing_tags) == 0:
Expand Down
4 changes: 3 additions & 1 deletion nf_core/subworkflows/lint/subworkflow_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,12 @@ def subworkflow_tests(_, subworkflow: NFCoreComponent):
included_components = []
if subworkflow.main_nf.is_file():
included_components = subworkflow._get_included_components(subworkflow.main_nf)
chained_components_tags = subworkflow._get_included_components_in_chained_tests(subworkflow.nftest_main_nf)
log.debug(f"Included components: {included_components}")
log.debug(f"Required tags: {required_tags}")
log.debug(f"Included components for chained nf-tests: {chained_components_tags}")
missing_tags = []
for tag in required_tags + included_components:
for tag in set(required_tags + included_components + chained_components_tags):
if tag not in main_nf_tags:
missing_tags.append(tag)
if len(missing_tags) == 0:
Expand Down
24 changes: 23 additions & 1 deletion tests/modules/lint.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

import pytest
import yaml
from git.repo import Repo

import nf_core.modules
from nf_core.modules.lint import main_nf
from nf_core.utils import set_wd

from ..utils import GITLAB_URL
from ..utils import GITLAB_NFTEST_BRANCH, GITLAB_URL
from .patch import BISMARK_ALIGN, CORRECT_SHA, PATCH_BRANCH, REPO_NAME, modify_main_nf


Expand Down Expand Up @@ -622,3 +623,24 @@ def test_modules_unused_pytest_files(self):
assert len(module_lint.passed) >= 0
assert len(module_lint.warned) >= 0
assert module_lint.failed[0].lint_test == "test_old_test_dir"


def test_nftest_failing_linting(self):
"""Test linting a module which includes other modules in nf-test tests.
Linting tests"""
# Clone modules repo with testing modules
tmp_dir = self.nfcore_modules.parent
self.nfcore_modules = Path(tmp_dir, "modules-test")
Repo.clone_from(GITLAB_URL, self.nfcore_modules, branch=GITLAB_NFTEST_BRANCH)

module_lint = nf_core.modules.ModuleLint(dir=self.nfcore_modules)
module_lint.lint(print_results=False, module="kallisto/quant")

assert len(module_lint.failed) == 4, f"Linting failed with {[x.__dict__ for x in module_lint.failed]}"
assert len(module_lint.passed) >= 0
assert len(module_lint.warned) >= 0
assert module_lint.failed[0].lint_test == "environment_yml_valid"
assert module_lint.failed[1].lint_test == "meta_yml_valid"
assert module_lint.failed[2].lint_test == "test_main_tags"
assert "kallisto/index" in module_lint.failed[2].message
assert module_lint.failed[3].lint_test == "test_tags_yml"
1 change: 1 addition & 0 deletions tests/test_modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ def test_modulesrepo_class(self):
test_modules_missing_test_dir,
test_modules_missing_test_main_nf,
test_modules_unused_pytest_files,
test_nftest_failing_linting,
)
from .modules.list import ( # type: ignore[misc]
test_modules_install_and_list_pipeline,
Expand Down

0 comments on commit fcf0c7e

Please sign in to comment.