feature:test

Table of contents

  1. Introduction
  2. Testing every feature
  3. Choosing the levels
  4. Running only some tests
  5. Which copy is tested
  6. Testing two features together
  7. Testing in a neutral app
    1. The platform
  8. Safety checks
  9. Advanced
  10. Reference
    1. Options
    2. Messages
  11. Requirements
  12. See also

Introduction

feature:test runs the tests of one feature, or of every feature of the selected product. The tests run in the product’s web container, against the product’s app or against a neutral app that holds the feature and nothing of the product. Run it while you work on a feature and before you release it.

splent feature:test reports
🧪 Running tests for reports [unit, integration, functional]...

  ▶  splent_feature_reports
     unit
4 passed in 0.15s
     integration
3 passed in 1.39s
     functional
1 passed in 1.22s

✅ Test runs (feature × level): 3 passed.

The summary counts pytest runs, one per feature and level. The test counts are pytest’s own lines above it. A failing run makes the command exit 1, so it stops a CI job.


Testing every feature

splent feature:test

Without a feature, it tests every feature the product declares for the current SPLENT_ENV. A feature with no copy on disk is skipped with a warning.

You can name a feature by its short name (notes), its package name (splent_feature_notes) or the entry the product declares (splent-io/splent_feature_notes@v1.12.0). A namespace or version you give must match the declaration, or the command stops.


Choosing the levels

splent feature:test --unit
splent feature:test reports --integration --functional

With no level flag it runs unit, integration and functional. Each flag picks one level, and you can combine them.

Level Tests Needs
--unit Services and helpers in isolation Mocks only
--integration Repositories, queries and relationships The test database
--functional Endpoints, redirects and rendered HTML Flask’s test client and the database
--e2e Whole browser flows A running server and Selenium
--load The test_*.py files under tests/load A running server

The scaffolded locustfile.py is not a pytest file, so run it with splent locust <feature>. feature:create scaffolds one folder per level under tests/, and Test levels explains how to write each one.


Running only some tests

splent feature:test -k test_publish -v

-k passes a keyword to pytest, so only the tests whose name matches run. -v turns on pytest’s verbose output.


Which copy is tested

The tests come from the first copy found.

  1. The working copy at the workspace root, <workspace>/<feature>/.
  2. The product’s link under features/ to the version it declares.
  3. That version in .splent_cache, when the product has no link to it yet.

So a feature you are editing is tested from its working copy, even when the product pins a release. The command says so.

  my_first_app pins splent_feature_notes at v1.18.0. This run tests the working copy in splent_feature_notes/ instead.

The app under test loads that same copy, through SPLENT_FEATURE_SOURCES, as Feature sources explains. Every other feature loads at the version the product declares. To test the pinned release itself, remove the working copy.


Testing two features together

splent feature:test reports --with notes --with mailer

When reports’ tests write notes through notes’ service, they run against the notes the product pins. If you are changing both, name the other one with --with. It loads from its working copy at the workspace root.

  Loading splent_feature_notes from its working copy in splent_feature_notes/ instead of v1.20.0, the version my_first_app pins.

A feature named with --with must have a working copy, and in the product’s app it must also be declared.


Testing in a neutral app

splent feature:test card_payments
splent feature:test landing --neutral

A feature the product does not declare is tested in a neutral app. --neutral chooses it for one the product declares, so a template, error handler or setting of your product cannot make a shared feature’s tests pass or fail. The neutral app is a new product, written to a temporary directory and removed after the run.

  splent_feature_card_payments is not declared in my_product, so its tests run in a neutral app.
  Neutral app: the framework, these features and their default configuration.
  Nothing of my_product reaches it but its test database.
    splent_feature_sessions_on_disk    v1.2.0        platform: where the sessions live
    splent_feature_accounts            v1.22.0       platform: who is signed in
    splent_feature_my_theme            v0.14.0       platform: the shells and the error pages
    splent_feature_shop                v0.5.0        required by card_payments
    splent_feature_card_payments       working copy  under test
The app holds Taken from
The feature under test Its working copy, or the release you name as <feature>@<version>
What it requires requires.features, requires.features_manual and the base it refines, at the newest release on the forge that meets each specifier, and what those require in turn
What its tests import Each feature an import, importlib.import_module or __import__ in its tests spells out, at its newest release. pytest.importorskip does not count
What its tests name [tool.splent.test] features, for features the tests reach in a way no scan reads
The platform One feature for sessions, sign-in and shells, unless a feature above already is it
--with FEATURE Its working copy, in place of the release, or in addition. It need not be declared anywhere
The configuration The framework’s defaults and each feature’s [tool.splent.config]

Name the features only the tests need in the feature’s pyproject.toml, with the same short names and specifiers as the contract.

[tool.splent.test]
features = ["shop>=0.9.0", "notes_tags"]

The tests get nothing of the product but its test database. Releases are cloned into .splent_cache when missing. When the forge does not answer, the newest cached release that meets the specifier is used.

When a feature asks for a Python package the product’s image lacks, the run installs it in a virtual environment of its own, in the same temporary directory. The image is never written to. SPLENT’s own packages are never installed this way, so a feature that needs a newer framework than the container’s stops the run.

The platform

A product cannot start or render without three things the framework leaves to features. The neutral app holds one feature for each, found by what it does, never by its name.

Capability A feature is it when
Where the sessions live Its config.py or __init__.py sets SESSION_TYPE
Who is signed in It sets up Flask-Login’s LoginManager
The shells It ships templates/public_base.html

A feature already in the app wins. Otherwise the command takes a release from .splent_cache, the one that requires the fewest other features, then the first by name. When none provides a capability, it stops.

❌ The neutral app cannot be put together: no release in .splent_cache provides sessions (a feature that sets SESSION_TYPE), and the app does not start without one. Name one in [tool.splent.test] features, or give a working copy with --with.

Safety checks

Before pytest runs, the command refuses to touch anything but a test database.

Check Refuses when
Production SPLENT_ENV=prod is in the product’s docker/.env, in the running web container, or in the command’s own environment there
TESTING TESTING is not True in the Flask configuration
Test database The database name lacks test, or is the development database (MARIADB_DATABASE)

In a neutral app the database is MARIADB_TEST_DATABASE, which must be set, contain test and differ from MARIADB_DATABASE. Messages show the URI with the password masked.

❌ Non-test database in use: <database>
   URI: <masked URI>

   Tests require a database with 'test' in its name, other than
   the development database (MARIADB_DATABASE).
   If a production deployment is running, stop it first:
     splent product:deploy --down

Advanced

From the CLI container, feature:test runs itself again in <product>_web with docker exec, as the user who owns the workspace, so what the tests write stays yours. It exits with that run’s code, and stopping the CLI with Ctrl-C stops the tests too.

A product runs one test run at a time, since they share the test database. A second run prints Another test run is using this product's test database. Waiting for it to finish... and waits.

A test that imports a model of a feature the app does not load fails only the query that meets it. See A model of a feature the app does not load.


Reference

Options

Option Description
FEATURE_REF The feature to test. Without it, every declared feature
--unit, --integration, --functional, --e2e, --load Run only these levels
-k KEYWORD Only tests whose name matches, passed to pytest
-v Verbose pytest output
--with FEATURE Load FEATURE from its working copy too. Repeatable
--neutral Test in a neutral app. Needs FEATURE_REF

Messages

Message Meaning
<level> skipped, no test_*.py files The level’s folder has no tests. A missing folder is skipped quietly
No tests ran. No test_*.py files at the selected levels. Nothing ran. Exits 0
<feature> not found on disk No copy of a declared feature
my_app declares splent_feature_notes pinned at v1.12.0, not v1.0.0. The version you gave is not the one declared
There is no copy of <feature> in the workspace to test An undeclared feature with no working copy and no cached release. Clone it first
--with <feature>, but <feature> has no working copy at the workspace root. Run splent feature:unlock <feature>
End-to-end tests drive the product's running server --e2e in a neutral app, which is never served
<requirer> requires shop>=2.0, and the release the neutral app loads is v1.22.0. No release meets every specifier
Cannot run tests in production. Stop the deployment with splent product:deploy --down
<product>_web is not running Start the product with splent product:up --dev

Requirements

  • A selected product (SPLENT_APP), up in development mode with splent product:up --dev. Its image installs splent_framework[dev], which brings pytest.

See also


Back to top

splent. Distributed by an LGPL license v3. Contact us: drorganvidez@us.es