Integration tests¶
Integration tests are Python tests that run against SQL Server instead of the in-memory database that unit tests use. They live in a top-level integration_tests/ folder and run with the --load-lime-test-integration-plugin option. They are optional: a project without the folder is complete.
Version requirement
The --load-lime-test-integration-plugin option requires lime-core 26.80.2 or later, which is bundled in lime-crm v3.82.0 and later.
When do you need integration tests?¶
Unit tests run against an in-memory database. That is fast and needs no setup, and it is the right choice for most business logic.
Write an integration test when the code under test depends on database behavior that the in-memory database does not reproduce, and you need to see it work against SQL Server.
Where do integration tests live?¶
Put integration tests in a folder named integration_tests in the root of the project, next to tests:
limepkg-my-package/
├── integration_tests/
│ ├── conftest.py
│ └── test_company_sync.py
├── limepkg_my_package/
├── tests/
│ ├── conftest.py
│ └── test_insanity.py
└── pyproject.toml
lime-project does not create the folder. Create it yourself when you write the first integration test.
Then make sure integration_tests is listed in norecursedirs in pyproject.toml, so that poetry run pytest skips the folder:
[tool.pytest.ini_options]
minversion = '6.0'
norecursedirs = [
'venv',
'.venv',
'build',
'dist',
'.plugins',
'frontend',
'integration_tests',
'.env',
'.git',
'.github',
'.lime',
'.vscode'
]
Without that entry, poetry run pytest also runs the integration tests, against the in-memory database.
How to run integration tests locally¶
You need two things on your machine:
- Docker, running.
lime-teststarts SQL Server in a container for the test run and stops it afterwards. - The Microsoft ODBC Driver 18 for SQL Server.
Run the tests from the root of the project:
The first run takes longer, because Docker downloads the SQL Server image.
Do not add the option to addopts
Adding --load-lime-test-integration-plugin to addopts in pyproject.toml makes every test run need SQL Server, including the unit tests in tests/. The tests then pass on a machine with Docker and the ODBC driver, and fail elsewhere with an error like Can't open lib 'ODBC Driver 18 for SQL Server'.
Pass the option on the command line, and only together with the integration_tests folder.
How to write an integration test¶
An integration test looks like a unit test and uses the same fixtures, such as lime_app and save_lime_objects:
def test_company_is_saved(lime_app, save_lime_objects):
company = lime_app.limetypes.company(name="Acme")
saved = save_lime_objects(company)
assert saved.id is not None
How do integration tests differ from unit tests?¶
The fixtures are used the same way in both kinds of tests, with these differences:
| Unit tests | Integration tests | |
|---|---|---|
database |
In-memory database | SQL Server |
| Data saved by a test | Gone when the test ends | Still there when the next test runs |
create_limetype_tables |
Available | Not supported — using it fails the test |
Because data stays between integration tests, a test must not assume that the database is empty unless you clean up after each test.
How to clean up data between integration tests¶
To remove the data a test leaves behind, define a fixture named mssql_truncate_tables that returns the tables to empty after each test. The table of a limetype has the same name as the limetype:
import pytest
@pytest.fixture(autouse=True)
def mssql_truncate_tables() -> list[str]:
return ["company", "person"]
Put the fixture in integration_tests/conftest.py to apply it to every integration test, or in a test module to apply it to that module only.
To drop tables instead of emptying them, define a fixture named mssql_delete_tables the same way. Both fixtures accept table names and compiled regular expressions:
import re
import pytest
@pytest.fixture(autouse=True)
def mssql_delete_tables() -> list[re.Pattern]:
return [re.compile(r"my_temporary_.+")]
How to share fixtures between tests and integration_tests¶
pytest only applies a conftest.py to the tests in the same folder and below it. Fixtures in tests/conftest.py are therefore not available in integration_tests/.
To use the same fixtures in both folders, move them to a conftest.py in the root of the project:
limepkg-my-package/
├── conftest.py # fixtures for both folders
├── integration_tests/
│ └── conftest.py # fixtures for integration tests only
├── tests/
│ └── conftest.py # fixtures for unit tests only
└── pyproject.toml
A fixture in the root conftest.py is used by both kinds of tests, so it must only rely on fixtures that work in both. For example, it cannot use create_limetype_tables.
Related pages¶
- Running tests compares unit tests and integration tests.
- Writing tests introduces
lime-testand the fixtures both kinds of tests share. - Testing best practices collects the practices we recommend for both kinds of tests.
- Fixtures is the reference for the
lime-testfixtures.