Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/test_and_deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ jobs:
- name: Run unit tests
run: pixi run test

- name: Run Integration Tests
run: pixi run integration-test

- name: Upload coverage to codecov
uses: codecov/codecov-action@v5
if: github.actor != 'dependabot[bot]'
Expand Down
2,284 changes: 849 additions & 1,435 deletions pixi.lock

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ build-docs = { cmd = 'sphinx-build -b html docs docs/_build', description = "Bui
test-docs = { cmd = "sphinx-build -M doctest docs docs/_build", description = "Test building the documentation" }
# Testing
test = { description = "Run the test suite", cmd = "pytest" }
integration-test = { description = "Run the integration test suite", cmd = "pytest -m integration" }
# Packaging
pypi-sdist = { cmd = "hatch build -t sdist", description = "Build the source distribution (tar.gz)" }
pypi-wheel = { cmd = "hatch build -t wheel", description = "Build the wheel distribution" }
Expand Down Expand Up @@ -211,7 +212,7 @@ reset-toml = { cmd = "cp pyproject.toml.bak pyproject.toml; rm pyproject.toml.ba
##############

[tool.pytest.ini_options]
addopts = "-v --cov=neutrons_standard --cov-report=term-missing"
addopts = "-m 'not (integration)' -v --cov=neutrons_standard --cov-report=term-missing"
pythonpath = [".", "src", "scripts"]
testpaths = ["tests"]
python_files = ["test*.py"]
Expand All @@ -223,7 +224,7 @@ norecursedirs = [
"*dataset*",
"*data_set*",
]
markers = ["mymarker: example markers goes here"]
markers = ["integration: mark a test as an integration test"]

############
### Ruff ###
Expand Down
2 changes: 1 addition & 1 deletion src/neutrons_standard/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.2.0.dev2"
__version__ = "0.0.0"
12 changes: 0 additions & 12 deletions src/neutrons_standard/help/help_model.py

This file was deleted.

27 changes: 27 additions & 0 deletions src/neutrons_standard/test/integration/test_base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@


import pytest

from neutrons_standard.test.integration.test_summary import TestSummary

@pytest.mark.integration
class IntegrationTest:
@pytest.fixture(scope="function", autouse=True) # noqa: PT003
def _setup(self):
self.test_summary = None

import faulthandler
faulthandler.enable()

yield

faulthandler.disable()

if self.test_summary is None:
raise RuntimeError("Integration test failed to initialize self.test_summary. Every integration test must build its own TestSummary object.")

if isinstance(self.test_summary, TestSummary):
if not self.test_summary.isComplete():
self.test_summary.FAILURE()
if self.test_summary.isFailure():
pytest.fail(f"Test Summary (-vv for full table): {self.test_summary}")
64 changes: 64 additions & 0 deletions src/neutrons_standard/test/integration/test_summary.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@

from enum import StrEnum

class TestSummary:
def __init__(self):
self._index = 0
self._steps = []

def SUCCESS(self):
step = self._steps[self._index]
step.status = self.TestStep.StepStatus.SUCCESS
self._index += 1

def FAILURE(self):
step = self._steps[self._index]
step.status = self.TestStep.StepStatus.FAILURE
self._index += 1

def SKIPPED(self):
step = self._steps[self._index]
step.status = self.TestStep.StepStatus.SKIPPED
self._index += 1

def isComplete(self):
return self._index == len(self._steps)

def isFailure(self):
return any(step.status == self.TestStep.StepStatus.FAILURE for step in self._steps)

def builder():
return TestSummary.TestSummaryBuilder()

def __str__(self):
longestStatus = max(len(step.status) for step in self._steps)
longestName = max(len(step.name) for step in self._steps)
tableCapStr = "#" * (longestName + longestStatus + 6)
tableStr = (
f"\n{tableCapStr}\n"
+ "\n".join(f"# {step.name:{longestName}}: {step.status:{longestStatus}} #" for step in self._steps)
+ f"\n{tableCapStr}\n"
)
return tableStr

class TestStep:
class StepStatus(StrEnum):
SUCCESS = "SUCCESS"
FAILURE = "FAILURE"
INCOMPLETE = "INCOMPLETE"
SKIPPED = "SKIPPED"

def __init__(self, name: str):
self.name = name
self.status = self.StepStatus.INCOMPLETE

class TestSummaryBuilder:
def __init__(self):
self.summary = TestSummary()

def step(self, name: str):
self.summary._steps.append(TestSummary.TestStep(name))
return self

def build(self):
return self.summary
15 changes: 15 additions & 0 deletions tests/test/integration/test_base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

from neutrons_standard.test.integration.test_base import IntegrationTest
from neutrons_standard.test.integration.test_summary import TestSummary


class TestIntegrationTest(IntegrationTest):

def test_init(self):
assert self.test_summary is None
self.test_summary = (
TestSummary.builder()
.step("Initialize Step!")
.build()
)
self.test_summary.SUCCESS()
Loading