class TestFlowSensor(unittest.TestCase): def setUp(self): self._mux = I2CMux(FLOW_SENSOR_MUX_ADDRESS) self._mux.select_channel(2) self._sensor = FlowSensor() def tearDown(self): self._sensor.close() self._mux.close() @unittest.skipIf(not is_on_raspberry_pi(), "The serial number won't be valid unless this " "is run on hardware.") def test_serial_number(self): serial_number = self._sensor.serial_number() self.assertTrue( 0 <= serial_number < 2**32, f"{serial_number} is not an unsigned 32-bit " "serial number") @unittest.skipIf(not is_on_raspberry_pi(), "Cannot determine ambient flow unless connected " "to hardware.") def test_ambient_flow(self): measured_flow = self._sensor.flow() self.assertTrue( math.isclose(measured_flow, 0, abs_tol=1), f"{measured_flow} != 0 +/- 0.1 slm : " "Fails to say that there is no flow in still " "air.\n" "Note that if this test is performed in a " "breezy environment, then the ambient flow may " "fall ouside the range of this test.")
class TestCommunicator(unittest.TestCase): def setUp(self): self._mux = I2CMux(constants.FLOW_SENSOR_MUX_ADDRESS) self._mux.select_channel(2) self._communicator = Communicator() def tearDown(self): self._communicator.close() self._mux.close() def test_is_present(self): self.assertTrue(self._communicator.is_present(), "Sensor is not useable at the moment.") def test_serial_number(self): serial_number = self._communicator.serial_number() self.assertTrue( 0 <= serial_number < 2**32, f"{serial_number:#x} is not an unsigned 32-bit " "serial number.") @unittest.skipIf(not is_on_raspberry_pi(), "Signal isn't 2 bytes + CRC8 unless connected " "to hardware.") def test_raw_flow(self): self._communicator.init_flow() raw_flow = self._communicator.raw_flow() self.assertTrue( 0 <= raw_flow < 2**16, f"{raw_flow:#x} is not an unsigned 16-bit flow " "number.")
def test_warn_when_i2c_isnt_available(self): if not is_on_raspberry_pi(): self._i2c.close() with self.assertWarns(UserWarning, msg="Fails to warn the user when I2C " "communication isn't available."): self._i2c = I2CInterface(0x70)
pass @abstractmethod def tubes_with_enough_sensors(self): """Returns a list of the ports with both a pressure sensor and a flow sensor. Returns ------- port_list : list A list of ints in range(constants.NUMBER_OF_PATIENTS) representing ports that have enough sensors. """ if is_on_raspberry_pi(): class Sensors(SensorsABC): def __init__(self, dump_communication=False): self._pressure_mux = I2CMux(constants.PRESSURE_SENSOR_MUX_ADDRESS) self._pressure_sensors = [] for i in range(constants.NUMBER_OF_PRESSURE_SENSORS): self._pressure_mux.select_channel(i) self._pressure_sensors.append( PressureSensor(dump_communication=dump_communication)) self._pressure_sensors[i].set_sampling( pressure_oversample=constants.PRESSURE_OVERSAMPLING, pressure_sampling_rate=constants.PRESSURE_RATE, temperature_oversample=constants.TEMPERATURE_OVERSAMPLING, temperature_sampling_rate=constants.TEMPERATURE_RATE) self._pressure_sensors[i].set_op_mode(
def step_impl(context): if is_on_raspberry_pi(): context.scenario.skip("Cannot automatically test that the " "sensor is not present unless this is " "run on hardware.") return
def step_impl(context): if not is_on_raspberry_pi(): context.scenario.skip("Cannot test that the sensor is present unless " "this is run on hardware.") return
class TestPressureSensor(unittest.TestCase): def setUp(self): self._mux = I2CMux(PRESSURE_SENSOR_MUX_ADDRESS) self._mux.select_channel(0) self._sensor = PressureSensor() def tearDown(self): self._sensor.close() self._mux.close() @unittest.skipIf(not is_on_raspberry_pi(), "Pressure sensor won't be present unless you're on " "hardware.") def test_is_present(self): self.assertTrue( self._sensor.is_present(), "Fails to identify that the sensor is present.\n" "Note that if the sensor is not connected, this " "test will fail.") @unittest.skipIf(is_on_raspberry_pi(), "This can only be tested non-interactively off of " "hardware.") def test_not_is_present(self): self.assertTrue( not self._sensor.is_present(), "Fails to correctly identify that a sensor is not " "present.") def test_set_op_mode_standby(self): self.assertEqual( self._sensor.set_op_mode(PressureSensor.OpMode.standby), PressureSensor.OpMode.standby, "Fails to put the sensor into Standby Mode.") def test_set_op_mode_background(self): self.assertEqual( self._sensor.set_op_mode(PressureSensor.OpMode.background), PressureSensor.OpMode.background, "Fails to put the sensor into Background Mode") def test_set_op_mode_command(self): self.assertEqual( self._sensor.set_op_mode(PressureSensor.OpMode.command), PressureSensor.OpMode.command, "Fails to put the sensor into Command Mode.") def test_set_sampling_default(self): self.assertTrue( self._sensor.set_sampling(), "Fails to successfully set the oversample and " "sampling rate to default values for temerature " "and pressure.") def test_set_sampling_valid_values(self): self.assertTrue( self._sensor.set_sampling(pressure_oversample=1, pressure_sampling_rate=1, temperature_oversample=1, temperature_sampling_rate=1), "Fails to set the oversample and sampling rate " "to valid custom values for temperature and " "pressure") def test_set_sampling_invalid_values(self): with self.assertRaises(ValueError, msg="Fails to raise a ValueError when " "oversample or temperature values are not " "in the set {1, 2, 4, 8, 16, 32, 64, 128}."): self._sensor.set_sampling(pressure_oversample=3, pressure_sampling_rate=3, temperature_oversample=3, temperature_sampling_rate=3) def test_pressure_without_sampling_set(self): self.assertTrue( math.isnan(self._sensor.pressure()), "Fails to return NaN for pressure when the user " "has not yet set the sampling parameters.") self.assertTrue( math.isnan(self._sensor.temperature()), "Fails to return NaN for temperature when the " "user has not yet set the sampling parameters.") @unittest.skipIf(not is_on_raspberry_pi(), "Cannot determine ambient temperature unless " "connected to hardware.") def test_ambient_temperature(self): self._sensor.set_op_mode(PressureSensor.OpMode.command) self._sensor.set_sampling(temperature_sampling_rate=8) measured_temperature = self._sensor.temperature() standard_temperature = 20 # degC relative_tolerance = 0.50 self.assertTrue( math.isclose(measured_temperature, standard_temperature, rel_tol=relative_tolerance), f"{measured_temperature} != " f"20 ± {int(100*relative_tolerance)}% degC :\n" "Fails to return ambient temperature in " "degC.\nNote that if this test is " "performed in a very cold or hot " "environment, the\nambient temperature " "may fall outside the range of this test.") @unittest.skipIf(not is_on_raspberry_pi(), "Cannot determine ambient pressure unless " "connected to hardware.") def test_ambient_pressure(self): self._sensor.set_sampling() self._sensor.set_op_mode(PressureSensor.OpMode.command) measured_pressure = self._sensor.pressure() standard_pressure = 101325 # Pa relative_tolerance = 0.10 self.assertTrue( math.isclose(measured_pressure, standard_pressure, rel_tol=relative_tolerance), f"{measured_pressure} != " f"101325 ± {int(100*relative_tolerance)}% Pa :\n" "Fails to return ambient pressure in Pa.\n" "Note that if this test is performed in a " "very low pressure environment,\nthe ambient " "pressure may fall outside the range of this " "test.")