Skip to content

Commit e104dc6

Browse files
committed
Improved pytest structure accordingly to the new schema
1 parent fa72b3b commit e104dc6

5 files changed

Lines changed: 365 additions & 403 deletions

File tree

Lines changed: 49 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,82 @@
1+
"""Validation tests for RVConfig, RqsGeneratorInput and SimulationSettings."""
2+
3+
from __future__ import annotations
4+
15
import pytest
26
from pydantic import ValidationError
37

48
from app.config.constants import Distribution, TimeDefaults
59
from app.schemas.random_variables_config import RVConfig
610
from app.schemas.requests_generator_input import RqsGeneratorInput
11+
from app.schemas.simulation_settings_input import SimulationSettings
12+
13+
# ---------------------------------------------------------------------------
14+
# RVCONFIG
15+
# ---------------------------------------------------------------------------
716

8-
# --------------------------------------------------------------------------
9-
# TEST RANDOM VARIABLE CONFIGURATION
10-
# --------------------------------------------------------------------------
1117

1218
def test_normal_sets_variance_to_mean() -> None:
13-
"""When distribution='normal' and variance is omitted, variance == mean."""
19+
"""If variance is omitted with 'normal', it defaults to mean."""
1420
cfg = RVConfig(mean=10, distribution=Distribution.NORMAL)
1521
assert cfg.variance == 10.0
1622

1723

1824
def test_poisson_keeps_variance_none() -> None:
19-
"""When distribution='poisson' and variance is omitted, variance stays None."""
25+
"""If variance is omitted with 'poisson', it remains None."""
2026
cfg = RVConfig(mean=5, distribution=Distribution.POISSON)
2127
assert cfg.variance is None
2228

2329

2430
def test_explicit_variance_is_preserved() -> None:
25-
"""If the user supplies variance explicitly, it is preserved unchanged."""
31+
"""An explicit variance value is not modified."""
2632
cfg = RVConfig(mean=8, distribution=Distribution.NORMAL, variance=4)
2733
assert cfg.variance == 4.0
2834

2935

3036
def test_mean_must_be_numeric() -> None:
31-
"""A non-numeric mean raises a ValidationError with our custom message."""
32-
with pytest.raises(ValidationError) as excinfo:
37+
"""A non numeric mean triggers a ValidationError."""
38+
with pytest.raises(ValidationError) as exc:
3339
RVConfig(mean="not a number", distribution=Distribution.POISSON)
3440

35-
# Check that at least one error refers to the 'mean' field
36-
assert any(err["loc"] == ("mean",) for err in excinfo.value.errors())
37-
assert "mean must be a number" in excinfo.value.errors()[0]["msg"]
41+
assert any(err["loc"] == ("mean",) for err in exc.value.errors())
3842

3943

4044
def test_missing_mean_field() -> None:
41-
"""Omitting the mean field raises a 'field required' ValidationError."""
42-
with pytest.raises(ValidationError) as excinfo:
43-
# Using model_validate avoids the constructor signature check
45+
"""Omitting mean raises a 'field required' ValidationError."""
46+
with pytest.raises(ValidationError) as exc:
4447
RVConfig.model_validate({"distribution": Distribution.NORMAL})
4548

4649
assert any(
4750
err["loc"] == ("mean",) and err["type"] == "missing"
48-
for err in excinfo.value.errors()
51+
for err in exc.value.errors()
4952
)
5053

51-
def test_gaussian_sets_variance_to_mean() -> None:
52-
"""When distribution='gaussian' and variance is omitted, variance == mean."""
53-
cfg = RVConfig(mean=12.5, distribution=Distribution.NORMAL)
54-
assert cfg.variance == pytest.approx(12.5)
55-
5654

5755
def test_default_distribution_is_poisson() -> None:
58-
"""
59-
When distribution is omitted, it defaults to 'poisson' and
60-
variance stays None.
61-
"""
56+
"""If distribution is missing, it defaults to 'poisson'."""
6257
cfg = RVConfig(mean=3.3)
6358
assert cfg.distribution == Distribution.POISSON
6459
assert cfg.variance is None
6560

6661

6762
def test_explicit_variance_kept_for_poisson() -> None:
68-
"""If the user supplies variance even for poisson, it is preserved."""
63+
"""Variance is kept even when distribution is poisson."""
6964
cfg = RVConfig(mean=4.0, distribution=Distribution.POISSON, variance=2.2)
7065
assert cfg.variance == pytest.approx(2.2)
7166

7267

7368
def test_invalid_distribution_raises() -> None:
74-
"""Supplying a non-supported distribution literal raises ValidationError."""
75-
with pytest.raises(ValidationError) as excinfo:
69+
"""An unsupported distribution literal raises ValidationError."""
70+
with pytest.raises(ValidationError):
7671
RVConfig(mean=5.0, distribution="not_a_dist")
7772

78-
errors = excinfo.value.errors()
79-
# Only assert there is at least one error for the 'distribution' field:
80-
assert any(e["loc"] == ("distribution",) for e in errors)
73+
# ---------------------------------------------------------------------------
74+
# RQSGENERATORINPUT - USER_SAMPLING_WINDOW
75+
# ---------------------------------------------------------------------------
8176

82-
# --------------------------------------------------------------------------
83-
# TEST FIELD VALIDATOR USER SAMPLING WINDOW
84-
# --------------------------------------------------------------------------
8577

8678
def test_default_user_sampling_window() -> None:
87-
"""When user_sampling_window is omitted, it defaults to USER_SAMPLING_WINDOW."""
79+
"""If user_sampling_window is missing it defaults to the constant."""
8880
inp = RqsGeneratorInput(
8981
avg_active_users={"mean": 1.0, "distribution": Distribution.POISSON},
9082
avg_request_per_minute_per_user={
@@ -96,47 +88,35 @@ def test_default_user_sampling_window() -> None:
9688

9789

9890
def test_explicit_user_sampling_window_kept() -> None:
99-
"""An explicit user_sampling_window value is preserved unchanged."""
100-
custom_window = 30
91+
"""An explicit user_sampling_window is preserved."""
10192
inp = RqsGeneratorInput(
10293
avg_active_users={"mean": 1.0, "distribution": Distribution.POISSON},
10394
avg_request_per_minute_per_user={
10495
"mean": 1.0,
10596
"distribution": Distribution.POISSON,
10697
},
107-
user_sampling_window=custom_window,
98+
user_sampling_window=30,
10899
)
109-
assert inp.user_sampling_window == custom_window
100+
assert inp.user_sampling_window == 30
110101

111102

112103
def test_user_sampling_window_not_int_raises() -> None:
113-
"""A non-integer user_sampling_window raises a ValidationError."""
114-
with pytest.raises(ValidationError) as excinfo:
115-
104+
"""A non integer user_sampling_window raises ValidationError."""
105+
with pytest.raises(ValidationError):
116106
RqsGeneratorInput(
117107
avg_active_users={"mean": 1.0, "distribution": Distribution.POISSON},
118108
avg_request_per_minute_per_user={
119109
"mean": 1.0,
120110
"distribution": Distribution.POISSON,
121111
},
122-
user_sampling_window="not-an-int",
112+
user_sampling_window="not-int",
123113
)
124114

125-
errors = excinfo.value.errors()
126-
assert any(err["loc"] == ("user_sampling_window",) for err in errors)
127-
128-
# Pydantic v2 wording
129-
assert any("valid integer" in err["msg"] for err in errors)
130-
131-
132115

133116
def test_user_sampling_window_above_max_raises() -> None:
134-
"""
135-
Passing user_sampling_window > MAX_USER_SAMPLING_WINDOW
136-
must raise a ValidationError.
137-
"""
117+
"""user_sampling_window above the max constant raises ValidationError."""
138118
too_large = TimeDefaults.MAX_USER_SAMPLING_WINDOW + 1
139-
with pytest.raises(ValidationError) as excinfo:
119+
with pytest.raises(ValidationError):
140120
RqsGeneratorInput(
141121
avg_active_users={"mean": 1.0, "distribution": Distribution.POISSON},
142122
avg_request_per_minute_per_user={
@@ -146,90 +126,33 @@ def test_user_sampling_window_above_max_raises() -> None:
146126
user_sampling_window=too_large,
147127
)
148128

149-
errors = excinfo.value.errors()
150-
assert any(err["loc"] == ("user_sampling_window",) for err in errors)
151-
152-
expected_snippet = (
153-
f"less than or equal to {TimeDefaults.MAX_USER_SAMPLING_WINDOW}"
154-
)
155-
assert any(expected_snippet in err["msg"] for err in errors)
156129

157130

131+
# ---------------------------------------------------------------------------
132+
# SIMULATIONSETTINGS - TOTAL_SIMULATION_TIME
133+
# ---------------------------------------------------------------------------
158134

159-
# --------------------------------------------------------------------------
160-
# TEST FIELD VALIDATOR TOTAL SIMULATION TIME
161-
# --------------------------------------------------------------------------
162135

163136
def test_default_total_simulation_time() -> None:
164-
"""When total_simulation_time is omitted, it defaults to SIMULATION_TIME."""
165-
inp = RqsGeneratorInput(
166-
avg_active_users={"mean": 1.0, "distribution": Distribution.POISSON},
167-
avg_request_per_minute_per_user={
168-
"mean": 1.0,
169-
"distribution": Distribution.POISSON,
170-
},
171-
)
172-
assert inp.total_simulation_time == TimeDefaults.SIMULATION_TIME
137+
"""If total_simulation_time is missing it defaults to the constant."""
138+
settings = SimulationSettings()
139+
assert settings.total_simulation_time == TimeDefaults.SIMULATION_TIME
173140

174141

175142
def test_explicit_total_simulation_time_kept() -> None:
176-
"""An explicit total_simulation_time value is preserved unchanged."""
177-
custom_time = 3_000
178-
inp = RqsGeneratorInput(
179-
avg_active_users={"mean": 1.0, "distribution": Distribution.POISSON},
180-
avg_request_per_minute_per_user={
181-
"mean": 1.0,
182-
"distribution": Distribution.POISSON,
183-
},
184-
total_simulation_time=custom_time,
185-
)
186-
assert inp.total_simulation_time == custom_time
143+
"""An explicit total_simulation_time is preserved."""
144+
settings = SimulationSettings(total_simulation_time=3_000)
145+
assert settings.total_simulation_time == 3_000
187146

188147

189148
def test_total_simulation_time_not_int_raises() -> None:
190-
"""A non-integer total_simulation_time raises a ValidationError."""
191-
with pytest.raises(ValidationError) as excinfo:
192-
193-
RqsGeneratorInput(
194-
avg_active_users={"mean": 1.0, "distribution": Distribution.POISSON},
195-
avg_request_per_minute_per_user={
196-
"mean": 1.0,
197-
"distribution": Distribution.POISSON,
198-
},
199-
total_simulation_time="three thousand",
200-
)
201-
202-
errors = excinfo.value.errors()
203-
assert any(err["loc"] == ("total_simulation_time",) for err in errors)
204-
205-
# Pydantic v2 wording: “Input should be a valid integer”
206-
assert any("valid integer" in err["msg"] for err in errors)
207-
149+
"""A non integer total_simulation_time raises ValidationError."""
150+
with pytest.raises(ValidationError):
151+
SimulationSettings(total_simulation_time="three thousand")
208152

209153

210154
def test_total_simulation_time_below_minimum_raises() -> None:
211-
"""
212-
Passing total_simulation_time < MIN_SIMULATION_TIME
213-
must raise a ValidationError.
214-
"""
155+
"""A total_simulation_time below the minimum constant raises ValidationError."""
215156
too_small = TimeDefaults.MIN_SIMULATION_TIME - 1
216-
with pytest.raises(ValidationError) as excinfo:
217-
RqsGeneratorInput(
218-
avg_active_users={"mean": 1.0, "distribution": Distribution.POISSON},
219-
avg_request_per_minute_per_user={
220-
"mean": 1.0,
221-
"distribution": Distribution.POISSON,
222-
},
223-
total_simulation_time=too_small,
224-
)
225-
226-
errors = excinfo.value.errors()
227-
# c'è almeno un errore sul campo giusto
228-
assert any(err["loc"] == ("total_simulation_time",) for err in errors)
229-
230-
expected_snippet = (
231-
f"greater than or equal to {TimeDefaults.MIN_SIMULATION_TIME}"
232-
)
233-
assert any(expected_snippet in err["msg"] for err in errors)
234-
235-
157+
with pytest.raises(ValidationError):
158+
SimulationSettings(total_simulation_time=too_small)

0 commit comments

Comments
 (0)