feat: pricing helper with regression tests
This commit is contained in:
commit
ca1ac6bfd4
39
Jenkinsfile
vendored
Normal file
39
Jenkinsfile
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// Test gate for the Hermes code-repair demo.
|
||||||
|
podTemplate(cloud: 'kubernetes', yaml: """
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
spec:
|
||||||
|
serviceAccountName: jenkins
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 1000
|
||||||
|
runAsGroup: 1000
|
||||||
|
fsGroup: 1000
|
||||||
|
fsGroupChangePolicy: "OnRootMismatch"
|
||||||
|
nodeSelector:
|
||||||
|
kubernetes.io/arch: arm64
|
||||||
|
node-role.kubernetes.io/worker: "true"
|
||||||
|
containers:
|
||||||
|
- name: python
|
||||||
|
image: python:3.12-slim
|
||||||
|
command: ["sleep"]
|
||||||
|
args: ["3600"]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
""") {
|
||||||
|
node(POD_LABEL) {
|
||||||
|
container('python') {
|
||||||
|
stage('Checkout') {
|
||||||
|
checkout scm
|
||||||
|
}
|
||||||
|
stage('tests') {
|
||||||
|
sh 'pip install --quiet pytest'
|
||||||
|
sh 'python -m pytest -v --junitxml=build/junit.xml'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
README.md
Normal file
9
README.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# hermes-code-demo
|
||||||
|
|
||||||
|
Deterministic source-defect fixture for the Hermes automated triage demo.
|
||||||
|
|
||||||
|
`src/discount.py` holds one small pricing helper covered by `tests/test_discount.py`.
|
||||||
|
The demo introduces a one-line defect on a branch, Jenkins fails the test gate,
|
||||||
|
Ariadne collects the evidence, and Hermes proposes a minimal patch that Ariadne
|
||||||
|
validates and pushes as a pull request for human review. Nothing merges
|
||||||
|
automatically.
|
||||||
2
pytest.ini
Normal file
2
pytest.ini
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[pytest]
|
||||||
|
pythonpath = .
|
||||||
13
src/discount.py
Normal file
13
src/discount.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
"""Order pricing helpers for the Hermes code-repair demo."""
|
||||||
|
|
||||||
|
|
||||||
|
def apply_discount(subtotal: float, percent: float) -> float:
|
||||||
|
"""Return the subtotal reduced by a whole-number discount percent.
|
||||||
|
|
||||||
|
Inputs: the order subtotal and a discount percent between 0 and 100.
|
||||||
|
Outputs: the discounted total, rounded to two decimal places.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if percent < 0 or percent > 100:
|
||||||
|
raise ValueError("percent must be between 0 and 100")
|
||||||
|
return round(subtotal * (1 - percent / 100), 2)
|
||||||
26
tests/test_discount.py
Normal file
26
tests/test_discount.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
"""Regression tests for the demo pricing helper."""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from src.discount import apply_discount
|
||||||
|
|
||||||
|
|
||||||
|
def test_no_discount_returns_subtotal() -> None:
|
||||||
|
assert apply_discount(100.0, 0) == 100.0
|
||||||
|
|
||||||
|
|
||||||
|
def test_ten_percent_off() -> None:
|
||||||
|
assert apply_discount(100.0, 10) == 90.0
|
||||||
|
|
||||||
|
|
||||||
|
def test_full_discount_is_free() -> None:
|
||||||
|
assert apply_discount(59.99, 100) == 0.0
|
||||||
|
|
||||||
|
|
||||||
|
def test_fractional_rounding() -> None:
|
||||||
|
assert apply_discount(19.99, 15) == 16.99
|
||||||
|
|
||||||
|
|
||||||
|
def test_rejects_out_of_range_percent() -> None:
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
apply_discount(10.0, 101)
|
||||||
Loading…
x
Reference in New Issue
Block a user