Skip to content

Commit

Permalink
update testing to allow for some simulation (#185)
Browse files Browse the repository at this point in the history
* update testing to allow for some simulation

* make a couple tests resilient to the X Series DUT
  • Loading branch information
zhindes authored Aug 22, 2022
1 parent 3e1261a commit cadf7b8
Show file tree
Hide file tree
Showing 21 changed files with 351 additions and 299 deletions.
94 changes: 72 additions & 22 deletions nidaqmx/tests/fixtures.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pytest
import nidaqmx.system
from enum import Enum
from nidaqmx.constants import ProductCategory, UsageTypeAI


Expand All @@ -11,23 +12,53 @@ class NoFixtureDetectedError(Error):
pass


@pytest.fixture(scope="module")
def x_series_device():
class DeviceType(Enum):
ANY = (-1,)
REAL = (0,)
SIMULATED = 1


def _x_series_device(device_type):
system = nidaqmx.system.System.local()

for device in system.devices:
if (not device.dev_is_simulated and
device.product_category == ProductCategory.X_SERIES_DAQ and
len(device.ao_physical_chans) >= 2 and
len(device.ai_physical_chans) >= 4 and
len(device.do_lines) >= 8 and
(len(device.di_lines) == len(device.do_lines)) and
len(device.ci_physical_chans) >= 4):
device_type_match = (
device_type == DeviceType.ANY
or (device_type == DeviceType.REAL and not device.dev_is_simulated)
or (device_type == DeviceType.SIMULATED and device.dev_is_simulated)
)
if (
device_type_match
and device.product_category == ProductCategory.X_SERIES_DAQ
and len(device.ao_physical_chans) >= 2
and len(device.ai_physical_chans) >= 4
and len(device.do_lines) >= 8
and len(device.di_lines) == len(device.do_lines)
and len(device.ci_physical_chans) >= 4
):
return device

raise NoFixtureDetectedError(
'Could not detect a device that meets the requirements to be an '
'X Series fixture. Cannot proceed to run tests.')
pytest.skip(
"Could not detect a device that meets the requirements to be an X Series fixture of type "
f"{device_type}. Cannot proceed to run tests. Import the NI MAX configuration file located "
"at nidaqmx\\tests\\max_config\\nidaqmxMaxConfig.ini to create these devices."
)
return None


@pytest.fixture(scope="module")
def any_x_series_device():
return _x_series_device(DeviceType.ANY)


@pytest.fixture(scope="module")
def real_x_series_device():
return _x_series_device(DeviceType.REAL)


@pytest.fixture(scope="module")
def sim_x_series_device():
return _x_series_device(DeviceType.SIMULATED)


@pytest.fixture(scope="module")
Expand All @@ -38,6 +69,11 @@ def bridge_device():
if UsageTypeAI.BRIDGE in device.ai_meas_types:
return device

pytest.skip(
"Could not detect a device that meets the requirements to be a bridge device. Cannot "
"proceed to run tests. Import the NI MAX configuration file located at "
"nidaqmx\\tests\\max_config\\nidaqmxMaxConfig.ini to create these devices."
)
return None


Expand All @@ -49,6 +85,11 @@ def sim_power_device():
if device.dev_is_simulated and UsageTypeAI.POWER in device.ai_meas_types:
return device

pytest.skip(
"Could not detect a device that meets the requirements to be a simulated power device. "
"Cannot proceed to run tests. Import the NI MAX configuration file located at "
"nidaqmx\\tests\\max_config\\nidaqmxMaxConfig.ini to create these devices."
)
return None


Expand All @@ -60,8 +101,15 @@ def sim_power_devices():
for device in system.devices:
if device.dev_is_simulated and UsageTypeAI.POWER in device.ai_meas_types:
devices.append(device)
if len(devices) == 2:
return devices

return devices
pytest.skip(
"Could not detect two or more devices that meets the requirements to be a simulated power "
"device. Cannot proceed to run tests. Import the NI MAX configuration file located at "
"nidaqmx\\tests\\max_config\\nidaqmxMaxConfig.ini to create these devices."
)
return None


@pytest.fixture(scope="module")
Expand All @@ -70,16 +118,18 @@ def multi_threading_test_devices():

devices = []
for device in system.devices:
if (device.dev_is_simulated and
device.product_category == ProductCategory.X_SERIES_DAQ and
len(device.ai_physical_chans) >= 1):
if (
device.dev_is_simulated
and device.product_category == ProductCategory.X_SERIES_DAQ
and len(device.ai_physical_chans) >= 1
):
devices.append(device)
if len(devices) == 4:
return devices

raise NoFixtureDetectedError(
'Could not detect 4 simulated X Series devices so as to meet the '
'requirements to be a multi-threading test test fixture. Cannot '
'proceed to run tests. Import the NI MAX configuration file located '
'at nidaqmx\\tests\\max_config\\nidaqmxMaxConfig.ini to create these '
'devices.')
pytest.skip(
"Could not detect 4 simulated X Series devices for multithreading tests. Cannot proceed "
"to run tests. Import the NI MAX configuration file located at "
"nidaqmx\\tests\\max_config\\nidaqmxMaxConfig.ini to create these devices."
)
return None
43 changes: 22 additions & 21 deletions nidaqmx/tests/test_channel_creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
CurrentShuntResistorLocation, TemperatureUnits, RTDType,
ResistanceConfiguration, ExcitationSource, ResistanceUnits, StrainUnits,
StrainGageBridgeType, BridgeConfiguration)
from nidaqmx.tests.fixtures import sim_power_device, x_series_device
from nidaqmx.tests.fixtures import sim_power_device, any_x_series_device
from nidaqmx.tests.helpers import generate_random_seed


Expand All @@ -24,11 +24,11 @@ class TestAnalogCreateChannels(object):
"""

@pytest.mark.parametrize('seed', [generate_random_seed()])
def test_create_ai_voltage_chan(self, x_series_device, seed):
def test_create_ai_voltage_chan(self, any_x_series_device, seed):
# Reset the pseudorandom number generator with seed.
random.seed(seed)

ai_phys_chan = random.choice(x_series_device.ai_physical_chans).name
ai_phys_chan = random.choice(any_x_series_device.ai_physical_chans).name

with nidaqmx.Task() as task:
ai_channel = task.ai_channels.add_ai_voltage_chan(
Expand All @@ -48,11 +48,11 @@ def test_create_ai_voltage_chan(self, x_series_device, seed):
"double_gain_scale")

@pytest.mark.parametrize('seed', [generate_random_seed()])
def test_create_ai_current_chan(self, x_series_device, seed):
def test_create_ai_current_chan(self, any_x_series_device, seed):
# Reset the pseudorandom number generator with seed.
random.seed(seed)

ai_phys_chan = random.choice(x_series_device.ai_physical_chans).name
ai_phys_chan = random.choice(any_x_series_device.ai_physical_chans).name

with nidaqmx.Task() as task:
ai_channel = task.ai_channels.add_ai_current_chan(
Expand All @@ -73,11 +73,11 @@ def test_create_ai_current_chan(self, x_series_device, seed):
assert ai_channel.ai_current_shunt_resistance == 100.0

# @pytest.mark.parametrize('seed', [generate_random_seed()])
# def test_create_ai_voltage_rms_chan(self, x_series_device, seed):
# def test_create_ai_voltage_rms_chan(self, any_x_series_device, seed):
# # Reset the pseudorandom number generator with seed.
# random.seed(seed)
#
# ai_phys_chan = random.choice(x_series_device.ai_physical_chans).name
# ai_phys_chan = random.choice(any_x_series_device.ai_physical_chans).name
#
# with nidaqmx.Task() as task:
# ai_channel = task.ai_channels.add_ai_voltage_rms_chan(
Expand All @@ -93,11 +93,11 @@ def test_create_ai_current_chan(self, x_series_device, seed):
# assert ai_channel.ai_custom_scale.name == ""

@pytest.mark.parametrize('seed', [generate_random_seed()])
def test_create_ai_rtd_chan(self, x_series_device, seed):
def test_create_ai_rtd_chan(self, any_x_series_device, seed):
# Reset the pseudorandom number generator with seed.
random.seed(seed)

ai_phys_chan = random.choice(x_series_device.ai_physical_chans).name
ai_phys_chan = random.choice(any_x_series_device.ai_physical_chans).name

with nidaqmx.Task() as task:
ai_channel = task.ai_channels.add_ai_rtd_chan(
Expand All @@ -121,11 +121,11 @@ def test_create_ai_rtd_chan(self, x_series_device, seed):
assert ai_channel.ai_rtd_r_0 == 100.0

@pytest.mark.parametrize('seed', [generate_random_seed()])
def test_create_ai_thrmstr_chan_iex(self, x_series_device, seed):
def test_create_ai_thrmstr_chan_iex(self, any_x_series_device, seed):
# Reset the pseudorandom number generator with seed.
random.seed(seed)

ai_phys_chan = random.choice(x_series_device.ai_physical_chans).name
ai_phys_chan = random.choice(any_x_series_device.ai_physical_chans).name

with nidaqmx.Task() as task:
ai_channel = task.ai_channels.add_ai_thrmstr_chan_iex(
Expand All @@ -151,11 +151,11 @@ def test_create_ai_thrmstr_chan_iex(self, x_series_device, seed):
assert ai_channel.ai_thrmstr_c == 0.000000102

@pytest.mark.parametrize('seed', [generate_random_seed()])
def test_create_ai_thrmstr_chan_vex(self, x_series_device, seed):
def test_create_ai_thrmstr_chan_vex(self, any_x_series_device, seed):
# Reset the pseudorandom number generator with seed.
random.seed(seed)

ai_phys_chan = random.choice(x_series_device.ai_physical_chans).name
ai_phys_chan = random.choice(any_x_series_device.ai_physical_chans).name

with nidaqmx.Task() as task:
ai_channel = task.ai_channels.add_ai_thrmstr_chan_vex(
Expand All @@ -182,19 +182,20 @@ def test_create_ai_thrmstr_chan_vex(self, x_series_device, seed):
assert ai_channel.ai_thrmstr_r_1 == 5000.0

@pytest.mark.parametrize('seed', [generate_random_seed()])
def test_create_ai_resistance_chan(self, x_series_device, seed):
def test_create_ai_resistance_chan(self, any_x_series_device, seed):
# Reset the pseudorandom number generator with seed.
random.seed(seed)

ai_phys_chan = random.choice(x_series_device.ai_physical_chans).name
ai_phys_chan = random.choice(any_x_series_device.ai_physical_chans).name

with nidaqmx.Task() as task:
# Note: 1000 ohms @ 5 mA = 5V range, which exists on most X Series devices.
ai_channel = task.ai_channels.add_ai_resistance_chan(
ai_phys_chan, name_to_assign_to_channel="ResistanceChannel",
min_val=-1000.0, max_val=1000.0, units=ResistanceUnits.OHMS,
resistance_config=ResistanceConfiguration.TWO_WIRE,
current_excit_source=ExcitationSource.EXTERNAL,
current_excit_val=0.002, custom_scale_name="")
current_excit_val=0.005, custom_scale_name="")

assert ai_channel.physical_channel.name == ai_phys_chan
assert ai_channel.name == "ResistanceChannel"
Expand All @@ -204,14 +205,14 @@ def test_create_ai_resistance_chan(self, x_series_device, seed):
assert (ai_channel.ai_resistance_cfg ==
ResistanceConfiguration.TWO_WIRE)
assert ai_channel.ai_excit_src == ExcitationSource.EXTERNAL
assert ai_channel.ai_excit_val == 0.002
assert ai_channel.ai_excit_val == 0.005

@pytest.mark.parametrize('seed', [generate_random_seed()])
def test_ai_strain_gage_chan(self, x_series_device, seed):
def test_ai_strain_gage_chan(self, any_x_series_device, seed):
# Reset the pseudorandom number generator with seed.
random.seed(seed)

ai_phys_chan = random.choice(x_series_device.ai_physical_chans).name
ai_phys_chan = random.choice(any_x_series_device.ai_physical_chans).name

with nidaqmx.Task() as task:
ai_channel = task.ai_channels.add_ai_strain_gage_chan(
Expand Down Expand Up @@ -239,11 +240,11 @@ def test_ai_strain_gage_chan(self, x_series_device, seed):
assert ai_channel.ai_lead_wire_resistance == 0.1

@pytest.mark.parametrize('seed', [generate_random_seed()])
def test_create_ai_voltage_chan_with_excit(self, x_series_device, seed):
def test_create_ai_voltage_chan_with_excit(self, any_x_series_device, seed):
# Reset the pseudorandom number generator with seed.
random.seed(seed)

ai_phys_chan = random.choice(x_series_device.ai_physical_chans).name
ai_phys_chan = random.choice(any_x_series_device.ai_physical_chans).name

with nidaqmx.Task() as task:
ai_channel = task.ai_channels.add_ai_voltage_chan_with_excit(
Expand Down
26 changes: 13 additions & 13 deletions nidaqmx/tests/test_channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import nidaqmx
import nidaqmx.system
from nidaqmx.constants import TaskMode
from nidaqmx.tests.fixtures import x_series_device
from nidaqmx.tests.fixtures import any_x_series_device, real_x_series_device
from nidaqmx.tests.helpers import generate_random_seed


Expand All @@ -14,51 +14,51 @@ class TestChannels(object):
objects in the NI-DAQmx Python API.
"""

def test_ai_channel(self, x_series_device):
def test_ai_channel(self, any_x_series_device):
with nidaqmx.Task() as task:
ai_channel = task.ai_channels.add_ai_voltage_chan(
x_series_device.ai_physical_chans[0].name, max_val=10)
any_x_series_device.ai_physical_chans[0].name, max_val=10)

# Test property default value.
assert ai_channel.ai_max == 10

def test_ao_channel(self, x_series_device):
def test_ao_channel(self, any_x_series_device):
with nidaqmx.Task() as task:
ao_channel = task.ao_channels.add_ao_voltage_chan(
x_series_device.ao_physical_chans[0].name, max_val=5)
any_x_series_device.ao_physical_chans[0].name, max_val=5)

# Test property default value.
assert ao_channel.ao_max == 5

def test_ci_channel(self, x_series_device):
def test_ci_channel(self, real_x_series_device):
with nidaqmx.Task() as task:
ci_channel = task.ci_channels.add_ci_count_edges_chan(
x_series_device.ci_physical_chans[0].name, initial_count=10)
real_x_series_device.ci_physical_chans[0].name, initial_count=10)

task.control(TaskMode.TASK_COMMIT)

assert ci_channel.ci_count == 10

def test_co_channel(self, x_series_device):
def test_co_channel(self, any_x_series_device):
with nidaqmx.Task() as task:
co_channel = task.co_channels.add_co_pulse_chan_freq(
x_series_device.co_physical_chans[0].name, freq=5000)
any_x_series_device.co_physical_chans[0].name, freq=5000)

task.control(TaskMode.TASK_COMMIT)

numpy.testing.assert_allclose(
[co_channel.co_pulse_freq], [5000], rtol=0.05)

def test_di_channel(self, x_series_device):
def test_di_channel(self, any_x_series_device):
with nidaqmx.Task() as task:
di_channel = task.di_channels.add_di_chan(
x_series_device.di_lines[0].name)
any_x_series_device.di_lines[0].name)

assert di_channel.di_num_lines == 1

def test_do_channel(self, x_series_device):
def test_do_channel(self, any_x_series_device):
with nidaqmx.Task() as task:
do_channel = task.do_channels.add_do_chan(
x_series_device.do_lines[0].name)
any_x_series_device.do_lines[0].name)

assert do_channel.do_num_lines == 1
Loading

0 comments on commit cadf7b8

Please sign in to comment.