Skip to content

Conversation

@klecki
Copy link
Contributor

@klecki klecki commented Dec 22, 2025

Use nose2 as the only testing framework. Drop nose.

Category: Other

Description:

Remove the WARs used to keep nose alive.

nose2 supports the yield-style test discovery by default @attr has a different filtering syntax (-A) and just checks for presence of truthy test_foo.attribute_name. A decorator uses this mechanism for backward compatibility.

nose2 splits with_setup(setup, teardown) into two separate decorators, a backward compatible decorator is added.

nottest sets special attribute.

SkipTest from unittest is recommended to be used directly (with the same functionality).

Test scripts are adjusted with minimal changes to run through nose2. Followup cleanup can be used for renaming.

Replace unsupported -m regex by attributes

Additional information:

Affected modules and functionalities:

Key points relevant for the review:

Tests:

  • Existing tests apply
  • New tests added
    • Python tests
    • GTests
    • Benchmark
    • Other
  • N/A

Checklist

Documentation

  • Existing documentation applies
  • Documentation updated
    • Docstring
    • Doxygen
    • RST
    • Jupyter
    • Other
  • N/A

DALI team only

Requirements

  • Implements new requirements
  • Affects existing requirements
  • N/A

REQ IDs: N/A

JIRA TASK: N/A

@greptile-apps
Copy link

greptile-apps bot commented Dec 22, 2025

Greptile Summary

This PR successfully migrates the DALI test suite from the deprecated nose framework to nose2, removing all nose dependencies and compatibility workarounds.

Key Changes:

  • Removed qa/nose_wrapper/__main__.py and all nose-specific Python 3.10+ compatibility code
  • Created nose2_attrib_generators.py plugin to handle attribute filtering on generator functions before execution
  • Updated nose_utils.py to use nose2/unittest equivalents (with_setup, attr, nottest, SkipTest)
  • Converted all test invocations across 24+ QA shell scripts from nose to nose2 syntax
  • Changed filter syntax from -m regex to -A 'attribute' for test selection
  • Updated test references from test_file.py to test_module and parametrized test syntax from :N to .N

Implementation Quality:
The compatibility layer in nose_utils.py maintains backward compatibility with existing test code while using nose2/unittest under the hood. The custom AttributeGeneratorFilter plugin is well-documented and solves nose2's limitation of executing generator functions before filtering by attributes.

Confidence Score: 4/5

  • Safe to merge with minor review of monkey-patching approach
  • The migration is comprehensive and well-executed. The custom plugin uses monkey-patching which is functional but fragile. Test invocations span many files making verification challenging.
  • Pay close attention to dali/test/python/nose2_attrib_generators.py for the monkey-patching implementation

Important Files Changed

Filename Overview
dali/test/python/nose2_attrib_generators.py New plugin to filter generator functions by attributes before execution - implements monkey-patching for nose2 compatibility
dali/test/python/nose_utils.py Replaced nose imports with nose2/unittest equivalents, removed Python 3.12 compatibility workarounds for nose
qa/test_template_impl.sh Removed nose framework, standardized on nose2 with updated test runner configuration
qa/TL0_python-self-test-core/test_body.sh Replaced nose commands with nose2 commands, changed test invocation syntax (.py to module names, : to .)
qa/TL0_python_self_test_frameworks/test_pytorch.sh Replaced nose regex filters (-m) with nose2 attribute filters (-A), updated test invocations

Sequence Diagram

sequenceDiagram
    participant TestScript as Test Script (QA)
    participant Nose2 as nose2 Runner
    participant AttribGen as AttributeGeneratorFilter Plugin
    participant AttribPlugin as AttributeSelector Plugin
    participant GenPlugin as Generators Plugin
    participant TestModule as Test Module
    
    TestScript->>Nose2: python -m nose2 -A 'pytorch' test_module
    Nose2->>AttribGen: handleArgs event
    AttribGen->>GenPlugin: Monkey-patch _testsFromGeneratorFunc
    Note over AttribGen,GenPlugin: Patches before test discovery
    
    Nose2->>TestModule: Discover tests
    TestModule->>GenPlugin: Found generator function
    GenPlugin->>AttribGen: patched_tests_from_gen(event, obj)
    AttribGen->>AttribPlugin: Check if @attr matches filter
    
    alt Attributes match
        AttribGen->>GenPlugin: Call original method
        GenPlugin->>TestModule: Execute generator, yield test cases
        TestModule-->>Nose2: Return test instances
    else Attributes don't match
        AttribGen-->>GenPlugin: Return empty list
        Note over AttribGen,GenPlugin: Skip without executing generator
    end
    
    Nose2->>TestModule: Run matched tests
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (1)

  1. dali/test/python/nose_utils.py, line 129-130 (link)

    style: creating a new TestCase instance for each assertion call is unconventional

    Consider creating a module-level instance once:

    Then define tc at module level (after imports) and reuse it in both assert_raises and assert_warns

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

25 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (2)

  1. dali/test/python/test_functional_api.py, line 22 (link)

    logic: This file still imports nose directly and uses nose.tools.eq_ on line 188. Since nose is being removed as a dependency, this will cause an import error.

  2. dali/test/python/test_functional_api.py, line 188 (link)

    logic: Replace nose.tools.eq_ with standard assertion or use assert_equals from nose_utils

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

28 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (1)

  1. dali/test/python/nose_utils.py, line 68 (link)

    syntax: missing self parameter - instance methods must have self as first parameter

29 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@klecki
Copy link
Contributor Author

klecki commented Dec 22, 2025

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [40627092]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [40627092]: BUILD FAILED

@klecki
Copy link
Contributor Author

klecki commented Dec 22, 2025

!build

with_teardown as _nose2_with_teardown,
)
from unittest import SkipTest # noqa: F401
import unittest

Check notice

Code scanning / CodeQL

Module is imported with 'import' and 'import from' Note test

Module 'unittest' is imported with both 'import' and 'import from'.
@dali-automaton
Copy link
Collaborator

CI MESSAGE: [40628704]: BUILD STARTED

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (1)

  1. dali/test/python/nose_utils.py, line 83-85 (link)

    style: Consider using the module-level _test_case instance instead of creating a new empty_case() for each assertion:

    This is more efficient and aligns with how assert_raises and assert_warns are implemented.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

29 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@JanuszL JanuszL self-assigned this Dec 22, 2025
@JanuszL
Copy link
Contributor

JanuszL commented Dec 22, 2025

Do we need to touch unittest_failure.cfg, unittest_slow.cfg or unittest.cfg as well?

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [40628704]: BUILD FAILED

Copy link
Contributor

@mzient mzient left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way the tests are first discovered and then run will most certainly prevent parallel external source from working (see test job 247483858) was the primary reason for not pursuing full transition to nose2 to date.
Perhaps you can move the troublesome tests to separate files to guarantee proper execution order.

Also, some of the tests used to generate vast amounts of data in the "discovery" stage, because yielding in nose didn't cause data accumulation. Please make sure that this is not the case any more - the tests might work when run one by one but case out-of-memory condition when multiple test files are run.

Remove the WARs used to keep nose alive.

nose2 supports the yield-style test discovery by default
@attr has a different filtering syntax (`-A`) and just checks for
presence of truthy test_foo.attribute_name. A decorator uses this
mechanism for backward compatibility.

nose2 splits with_setup(setup, teardown) into two separate decorators,
a backward compatible decorator is added.

nottest sets special attribute.

SkipTest from unittest is recommended to be used directly (with the same
functionality).

Test scripts are adjusted with minimal changes to run through nose2.
Followup cleanup can be used for renaming.

Signed-off-by: Krzysztof Lecki <klecki@nvidia.com>
Signed-off-by: Krzysztof Lecki <klecki@nvidia.com>
Signed-off-by: Krzysztof Lecki <klecki@nvidia.com>
Signed-off-by: Krzysztof Lecki <klecki@nvidia.com>
Signed-off-by: Krzysztof Lecki <klecki@nvidia.com>
Signed-off-by: Krzysztof Lecki <klecki@nvidia.com>
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (1)

  1. dali/test/python/nose_utils.py, line 74 (link)

    syntax: Missing self parameter in method definition

33 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Signed-off-by: Krzysztof Lecki <klecki@nvidia.com>
@greptile-apps
Copy link

greptile-apps bot commented Dec 30, 2025

Greptile's behavior is changing!

From now on, if a review finishes with no comments, we will not post an additional "statistics" comment to confirm that our review found nothing to comment on. However, you can confirm that we reviewed your changes in the status check section.

This feature can be toggled off in your Code Review Settings by deselecting "Create a status check for each PR".

@klecki
Copy link
Contributor Author

klecki commented Dec 30, 2025

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [40968438]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [40968438]: BUILD FAILED

Signed-off-by: Krzysztof Lecki <klecki@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants