Using Specter

Installation

You can download Specter from PyPI for easy installation. It is recommended that you use pip or easy_install to install the bindings:

pip install specter

You may consider using virtualenv or pyenv to create isolated Python environments.

Setup

By default, Specter looks within the current directory for a folder called “spec” which contains your test files

Example Default Test Structure:

Project_Folder
    └── spec
        ├── submodule
            ├── another.py
            └── __init__.py
        ├── example.py
        └── __init__.py

If you do not wish to use the default folder, you can specify an alternative using the "--search" command-line argument:

specter --search /path/to/folder

Runner

Specter allows for quick and easy execution of your tests by just calling ‘specter’ within your project folder:

specter
          ___
        _/ @@\
    ~- ( \  O/__     Specter
    ~-  \    \__)   ~~~~~~~~~~
    ~-  /     \     Keeping the Bogeyman away from your code!
    ~- /      _\
       ~~~~~~~~~

ExampleSpec
  ∟ this is a test spec


------------------------
------- Summary --------
Pass            | 1
Skip            | 0
Fail            | 0
Error           | 0
Incomplete      | 0
Test Total      | 1
 - Expectations | 1

------------------------

Command-line Arguments

Specter is a spec-based testing library to help facilitate BDD in Python.

Argument

Description

-h, –help

Show console help

–search PATH

Specifies the search path for spec files

–no-art

Disables the ASCII art on the runner

–coverage

Enables coverage.py integration. Configure using .coveragerc

–select-module

Selects a module path to run. Ex: sample.TestClass

–select-tests

Selects tests to run by name. (Comma delimited list)

–select-by-metadata

Selects tests to run by specifying a list of key=value pairs

–xunit-results

Output xUnit XML results into a specified file

–json-results

Saves Specter JSON results into a specifed file

–no-color

Disables ASCII color codes

–ascii-only

Disables color and uses only ascii characters (useful for CI systems).

–parallel

Activates parallel testing mode

–num-processes

Specifies the number of processes to use under parallel mode (default: 6)

–show-all-expects

Displays all expectations for test cases

Selecting Tests

Specter provides three ways to select a subset of tests at run time. They can be combined: for example, --select-module narrows the search space and --select-by-metadata then filters within that module.

By module

--select-module accepts a dot-separated module path matching the class hierarchy inside your spec/ folder:

specter --select-module spec.users.UserCreationSpec

You can also target a whole sub-package:

specter --select-module spec.users

By test name

--select-tests accepts a comma-separated list of test method names (without the class prefix). The match is exact:

# Run a single test
specter --select-tests it_creates_a_user

# Run multiple tests
specter --select-tests it_creates_a_user,it_deletes_a_user

By metadata

--select-by-metadata accepts a space-separated list of key=value pairs. Only tests decorated with matching metadata() tags are run:

# Run only smoke tests
specter --select-by-metadata type=smoke

# Run tests tagged as both smoke and positive
specter --select-by-metadata type=smoke kind=positive

Combining selectors

All three selectors can be combined in a single invocation. The module filter is applied first, then the name/metadata filters operate on the resulting set:

specter --select-module spec.api \
        --select-by-metadata type=smoke \
        --xunit-results results/smoke.xml

Coverage

Enable coverage tracking by passing --coverage. Configure what to include or exclude using a .coveragerc file in your project root.

Minimal .coveragerc example:

[run]
source = mypackage
omit =
    spec/*
    */vendor/*

[report]
show_missing = True

Then run:

specter --coverage

CI/CD Integration

Specter integrates with CI pipelines through its xUnit XML output (--xunit-results) and --ascii-only flag, which removes color codes and Unicode symbols that can confuse log parsers.

GitHub Actions

name: Tests
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.10", "3.11", "3.12", "3.13"]

    steps:
      - uses: actions/checkout@v4

      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}

      - name: Install dependencies
        run: pip install -e .[dev]

      - name: Run tests
        run: specter --ascii-only --xunit-results results/xunit.xml

      - name: Publish test results
        uses: EnricoMi/publish-unit-test-result-action@v2
        if: always()
        with:
          files: results/xunit.xml

GitLab CI

test:
  image: python:3.12
  script:
    - pip install -e .[dev]
    - specter --ascii-only --xunit-results results/xunit.xml
  artifacts:
    when: always
    reports:
      junit: results/xunit.xml

Jenkins

pipeline {
    agent any
    stages {
        stage('Test') {
            steps {
                sh 'pip install -e .[dev]'
                sh 'specter --ascii-only --xunit-results results/xunit.xml'
            }
            post {
                always {
                    junit 'results/xunit.xml'
                }
            }
        }
    }
}

Running with coverage in CI

Add --coverage to any of the commands above and configure .coveragerc as shown in the Coverage section. The coverage report is printed to stdout at the end of the run.