Skip to content

Components Test Management

Karthik Nadig edited this page Jan 27, 2021 · 1 revision

The extension provides testing for Python code through one of the supported frameworks. This involves a variety of capabilities in addition to just running tests. The following frameworks are supported:

Functionality

operations

  • install selected test framework if not installed
  • test discovery
  • run all/selected tests & suites
  • debug all/selected tests & suites
  • breakpoints while running tests
  • show (high level) test results

Note that the active Python interpreter is used for all testing operations.

resources

  • (somewhat) granular test framework config settings
  • dedicated output log

commands

  • "Python: Discover Unit Tests"
  • "Python: Run All Unit Tests"
  • "Python: Run Unit Test Method..."
  • "Python: View Unit Test Output"

UI

  • status bar element
    • shows test results
    • triggers quick pick for testing-related operations
  • pop-up (& quick pick) to configure test framework
  • code lens on tests and suites:
    • run/debug
    • results
  • output panel: "Python Test Log"
  • TBD: Test Explorer activity (top-level VSC element)

config settings

  • "python.unitTest.cwd"
  • "python.unitTest.debugPort"
  • "python.unitTest.nosetestArgs"
  • "python.unitTest.nosetestsEnabled"
  • "python.unitTest.nosetestPath"
  • "python.unitTest.promptToConfigure"
  • "python.unitTest.pyTestArgs"
  • "python.unitTest.pyTestEnabled"
  • "python.unitTest.pyTestPath"
  • "python.unitTest.unittestArgs"
  • "python.unitTest.unittestEnabled"
  • "python.unitTest.autoTestDiscoverOnSaveEnabled"

Extension Code

codebase structure

All test-related code is contained entirely under a single directory, src/client/unittests/:

src/client/unittest
├── codeLenses
├── common
│   ├── managers
│   ├── services
│   └── testVisitors
├── display
├── nosetest
│   └── services
├── pytest
│   └── services
└── unittest
    └── services

files: external API

src/client/unittest
├── serviceRegistry.ts
└── types.ts

files: top-level code

src/client/unittest
├── common
│   ├── argumentsHelper.ts
│   ├── constants.ts
│   ├── debugLauncher.ts
│   ├── managers
│   │   ├── baseTestManager.ts
│   │   └── testConfigurationManager.ts
│   ├── runner.ts
│   ├── services
│   │   ├── configSettingService.ts
│   │   ├── storageService.ts
│   │   ├── testManagerService.ts
│   │   ├── testResultsService.ts
│   │   ├── unitTestDiagnosticService.ts
│   │   └── workspaceTestManagerService.ts
│   ├── testUtils.ts
│   ├── testVisitors
│   │   ├── flatteningVisitor.ts
│   │   ├── folderGenerationVisitor.ts
│   │   └── resultResetVisitor.ts
│   ├── types.ts
│   └── xUnitParser.ts
└── main.ts

files: configuration:

src/client/unittest
├── configurationFactory.ts
├── configuration.ts
├── nosetest
│   └── testConfigurationManager.ts
├── pytest
│   └── testConfigurationManager.ts
└── unittest
    └── testConfigurationManager.ts

files: testing frameworks:

src/client/unittest
├── nosetest
│   ├── main.ts
│   ├── runner.ts
│   └── services
│       ├── argsService.ts
│       ├── discoveryService.ts
│       └── parserService.ts
├── pytest
│   ├── main.ts
│   ├── runner.ts
│   └── services
│       ├── argsService.ts
│       ├── discoveryService.ts
│       ├── parserService.ts
│       └── testMessageService.ts
└── unittest
    ├── helper.ts
    ├── main.ts
    ├── runner.ts
    ├── services
    │   ├── argsService.ts
    │   ├── discoveryService.ts
    │   └── parserService.ts
    └── socketServer.ts

files: UI features

src/client/unittest
├── codeLenses
│   ├── main.ts
│   └── testFiles.ts
└── display
    ├── main.ts
    └── picker.ts

components

  • config
  • test discovery
  • code lens
  • picker
  • runner

Adapter Script

  • source: pythonFiles/testing_tools/adapter/__main__.py
  • invocation:
    • [PYTHON] [SCRIPT] discover pytest [ARGS] -- [PYTEST ARGS]
    • SCRIPT (any python): pythonFiles/testing_tools/run_adapter.py
    • SCRIPT (python3-only): -m pythonFiles.testing_tools.adapter
  • args:
    • --simple - simplified output for use while debugging
    • --no-hide-stdio - do not hide pytest stdout/stderr during discover (useful when debugging)
    • --pretty - format output for readability
  • implicit pytest args:
    • --collect-only

Output

OUTPUT: ROOTED_TESTS[]
ROOTED_TESTS: {
    # Uniquely identifies test root.
    "rootid": str
    # Absolute path to test root.
    "root": str
    # The discovered files, suites, etc. under this root.
    "parents": PARENT[]
    # The discovered tests under this root.
    "tests": TEST[]
}
PARENT: {
    # Uniquely identifies the parent.
    "id": str
    # The kind of parent.
    "kind": "folder"|"file"|"suite"|"function"|"subtest"
    # A human-friendly identifier.
    "name": str
    # The parent's parent (i.e. in a tree from the root.
    "parentid": str
}
TEST: {
    # Uniquely identifies the test.
    "id": str
    # A human-friendly identifier.
    "name": str
    # The location of the test's source code.
    "source": str ("<FILENAME>:<LINENO>")
    # Any supported markers associated with the test.
    "markers": ("skip"|"skip-if"|"expected-failure")[]
    # The ID of the test's parent.
    "parentid": str
}

Notes:

  • IDs may be used to identify a test or parent to the test framework (e.g. to run specific tests)
  • every child of the root will have the "rootid" as its "parentid"
  • supported test markers are framework-agnostic but correspond to framework-specific ones
  • a test is considered a "subtest" if its parent is a function or a subtest
  • a subtest is a test that is effectively a parameterization of a more general test
    • in pytest parameterized tests are the only kind of subtest
  • a subtest may be a parent if there is a nested subtest in it
    • this is not supported in pytest, but is in unittest

Example:

[{
    "rootid": ".",
    "root": "/x/y/z",
    "parents": [{
        "id": "./test_spam.py",
        "kind": "file",
        "name": "test_spam.py",
        "parentid": "."
    }, {
        "id": "./test_spam.py::SpamTests",
        "kind": "suite",
        "name": "SpamTests",
        "parentid": "./test_spam.py"
    },
    "tests" [{
        "id": "./test_spam.py::test_all",
        "name": "test_all",
        "source": "test_spam.py:11",
        "markers": ["skip", "expected-failure"],
        "parentid": "./test_spam.py"
    }, {
        "id": "./test_spam.py::SpamTests::test_spam1",
        "name": "test_spam1",
        "source": "test_spam.py:23",
        "markers": ["skip"],
        "parentid": "./test_spam.py::SpamTests"
    }]
}]
Clone this wiki locally
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy