Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nf-test linting tags #2572

Merged
merged 4 commits into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading