Fix TempCo integration tests with thread-based async server
Redesign integration test architecture to eliminate async/sync deadlock: - Run SimulationServer in dedicated background thread with own event loop - Rewrite TempCo tests as fully synchronous (no @pytest.mark.asyncio) - Add ServerThread fixture in tests/integration/conftest.py - Fix Unicode encoding errors (replace deg, mu, +/- with ASCII) - Optimize temperature points for faster settling (23C, 25C, 27C) All 3 TempCo integration tests now passing in ~5 minutes total.
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
This test characterises the output voltage temperature coefficient by
|
||||
sweeping the chamber temperature and measuring output voltage at each point.
|
||||
The TempCo is calculated from the linear regression slope and expressed
|
||||
in parts per million per degree Celsius (ppm/°C).
|
||||
in parts per million per degree Celsius (ppm/C).
|
||||
"""
|
||||
|
||||
from py_dvt_ate.data.models import TestStatus
|
||||
@@ -29,12 +29,12 @@ class TempCoTest(BaseDVTTest):
|
||||
5. Evaluate against specification limits
|
||||
|
||||
Configuration:
|
||||
temperatures: List of temperature points (°C). Default: [-40, -20, 0, 25, 50, 85]
|
||||
temperatures: List of temperature points (C). Default: [-40, -20, 0, 25, 50, 85]
|
||||
input_voltage: DUT input voltage (V). Default: 5.0
|
||||
load_current: DUT load current (A). Default: 0.1
|
||||
settle_time: Additional settling time at each temp (s). Default: 5.0
|
||||
num_samples: Number of measurements to average per point. Default: 5
|
||||
tempco_limit: Maximum allowed TempCo magnitude (ppm/°C). Default: ±50.0
|
||||
tempco_limit: Maximum allowed TempCo magnitude (ppm/C). Default: +/-50.0
|
||||
"""
|
||||
|
||||
@property
|
||||
@@ -90,7 +90,7 @@ class TempCoTest(BaseDVTTest):
|
||||
# Temperature sweep
|
||||
for temp_setpoint in temperatures:
|
||||
context.logger.log_event(
|
||||
f"Temperature point: {temp_setpoint}°C",
|
||||
f"Temperature point: {temp_setpoint}C",
|
||||
level="INFO",
|
||||
)
|
||||
|
||||
@@ -102,7 +102,7 @@ class TempCoTest(BaseDVTTest):
|
||||
)
|
||||
if not stable:
|
||||
context.logger.log_event(
|
||||
f"Warning: Temperature did not stabilise at {temp_setpoint}°C",
|
||||
f"Warning: Temperature did not stabilise at {temp_setpoint}C",
|
||||
level="WARNING",
|
||||
)
|
||||
|
||||
@@ -133,8 +133,8 @@ class TempCoTest(BaseDVTTest):
|
||||
)
|
||||
|
||||
context.logger.log_event(
|
||||
f"Measured Vout = {vout_mean:.6f}V ± {vout_std * 1e6:.1f}μV "
|
||||
f"at T={actual_temp:.2f}°C",
|
||||
f"Measured Vout = {vout_mean:.6f}V +/- {vout_std * 1e6:.1f}uV "
|
||||
f"at T={actual_temp:.2f}C",
|
||||
level="INFO",
|
||||
)
|
||||
|
||||
@@ -146,7 +146,7 @@ class TempCoTest(BaseDVTTest):
|
||||
tempco_ppm = self._calculate_tempco(temp_points, vout_points)
|
||||
|
||||
context.logger.log_event(
|
||||
f"Calculated TempCo = {tempco_ppm:.2f} ppm/°C",
|
||||
f"Calculated TempCo = {tempco_ppm:.2f} ppm/C",
|
||||
level="INFO",
|
||||
)
|
||||
|
||||
@@ -154,7 +154,7 @@ class TempCoTest(BaseDVTTest):
|
||||
context.logger.log_result(
|
||||
parameter="temp_co",
|
||||
value=tempco_ppm,
|
||||
unit="ppm/°C",
|
||||
unit="ppm/C",
|
||||
lower_limit=-abs(tempco_limit),
|
||||
upper_limit=abs(tempco_limit),
|
||||
)
|
||||
@@ -164,13 +164,13 @@ class TempCoTest(BaseDVTTest):
|
||||
|
||||
if passed:
|
||||
context.logger.log_event(
|
||||
f"TempCo test PASSED: {tempco_ppm:.2f} ppm/°C within ±{tempco_limit} ppm/°C",
|
||||
f"TempCo test PASSED: {tempco_ppm:.2f} ppm/C within +/-{tempco_limit} ppm/C",
|
||||
level="INFO",
|
||||
)
|
||||
return TestStatus.PASSED
|
||||
else:
|
||||
context.logger.log_event(
|
||||
f"TempCo test FAILED: {tempco_ppm:.2f} ppm/°C exceeds ±{tempco_limit} ppm/°C",
|
||||
f"TempCo test FAILED: {tempco_ppm:.2f} ppm/C exceeds +/-{tempco_limit} ppm/C",
|
||||
level="ERROR",
|
||||
)
|
||||
return TestStatus.FAILED
|
||||
@@ -198,14 +198,14 @@ class TempCoTest(BaseDVTTest):
|
||||
"""Calculate temperature coefficient from measurements.
|
||||
|
||||
Uses linear regression to find the slope (dV/dT), then converts
|
||||
to ppm/°C relative to the nominal voltage (voltage at median temperature).
|
||||
to ppm/C relative to the nominal voltage (voltage at median temperature).
|
||||
|
||||
Args:
|
||||
temperatures: Temperature measurements in °C.
|
||||
temperatures: Temperature measurements in C.
|
||||
voltages: Output voltage measurements in V.
|
||||
|
||||
Returns:
|
||||
Temperature coefficient in ppm/°C.
|
||||
Temperature coefficient in ppm/C.
|
||||
|
||||
Raises:
|
||||
ValueError: If insufficient data points.
|
||||
@@ -230,14 +230,14 @@ class TempCoTest(BaseDVTTest):
|
||||
if var_t == 0:
|
||||
raise ValueError("Temperature variance is zero (all temps identical)")
|
||||
|
||||
slope = cov / var_t # dV/dT in V/°C
|
||||
slope = cov / var_t # dV/dT in V/C
|
||||
|
||||
# Find nominal voltage (voltage at median temperature)
|
||||
sorted_pairs = sorted(zip(temperatures, voltages, strict=True))
|
||||
mid_idx = len(sorted_pairs) // 2
|
||||
v_nominal = sorted_pairs[mid_idx][1]
|
||||
|
||||
# Convert to ppm/°C: (dV/dT) / V_nom * 10^6
|
||||
# Convert to ppm/C: (dV/dT) / V_nom * 10^6
|
||||
tempco_ppm = (slope / v_nominal) * 1e6
|
||||
|
||||
return tempco_ppm
|
||||
|
||||
Reference in New Issue
Block a user