From d485940e9ee6b4e28b46fba67360bf51fecb1632 Mon Sep 17 00:00:00 2001 From: PeterMeisrimelModelon <92585725+PeterMeisrimelModelon@users.noreply.github.com> Date: Mon, 12 Feb 2024 17:01:50 +0100 Subject: [PATCH] Replacing nose by pytest --- .github/workflows/build.yml | 4 +- setup.cfg | 2 +- src/pyfmi/__init__.py | 14 -- tests/test_fmi.py | 357 ++++++++++++++---------------------- tests/test_fmi_coupled.py | 63 +++---- tests/test_fmi_estimate.py | 3 - tests/test_fmi_extended.py | 3 - tests/test_fmi_master.py | 31 +--- tests/test_fmi_util.py | 4 - tests/test_io.py | 263 ++++++++------------------ tests/test_log.py | 19 +- tests/test_stream.py | 43 ++--- 12 files changed, 270 insertions(+), 536 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 31cc431c..12bf70e9 100755 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,7 +15,7 @@ jobs: python-version: '3.11.x' - name: Setup Python run: | - python3 -m pip install Cython numpy scipy matplotlib nose-py3 + python3 -m pip install Cython numpy scipy matplotlib pytest - name: Install system run: | sudo apt-get -y install cmake liblapack-dev libsuitesparse-dev libhypre-dev @@ -59,4 +59,4 @@ jobs: run: | rm src/pyfmi/__init__.py cp -rv src/pyfmi/tests/files tests - python3 -m nose --verbose tests/*.py + pytest --verbose tests/ diff --git a/setup.cfg b/setup.cfg index ae02d747..50f3ede2 100644 --- a/setup.cfg +++ b/setup.cfg @@ -8,6 +8,6 @@ install_requires = numpy >= 1.26.3 scipy >= 1.11.4 cython >= 3.0.7 - nose-py3 >= 1.6.3 + pytest >= 7.4.4 matplotlib > 3 assimulo >= 3.5.0 diff --git a/src/pyfmi/__init__.py b/src/pyfmi/__init__.py index 49d628c6..54ed6beb 100644 --- a/src/pyfmi/__init__.py +++ b/src/pyfmi/__init__.py @@ -34,20 +34,6 @@ int = np.int32 np.int = np.int32 -def testattr(**kwargs): - """Add attributes to a test function/method/class. - - This function is needed to be able to add - @attr(slow = True) - for functions. - - """ - def wrap(func): - func.__dict__.update(kwargs) - return func - return wrap - - try: curr_dir = os.path.dirname(os.path.abspath(__file__)) _fpath=os.path.join(curr_dir,'version.txt') diff --git a/tests/test_fmi.py b/tests/test_fmi.py index 3b46e907..88d73056 100644 --- a/tests/test_fmi.py +++ b/tests/test_fmi.py @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import nose +import pytest import os import numpy as np from zipfile import ZipFile @@ -24,7 +24,6 @@ import logging from io import StringIO -from pyfmi import testattr from pyfmi.fmi import FMUException, InvalidOptionException, InvalidXMLException, InvalidBinaryException, InvalidVersionException, FMUModelME1, FMUModelCS1, load_fmu, FMUModelCS2, FMUModelME2 import pyfmi.fmi as fmi from pyfmi.fmi_algorithm_drivers import AssimuloFMIAlg, AssimuloFMIAlgOptions, \ @@ -70,12 +69,11 @@ def _helper_unzipped_fmu_exception_invalid_dir(fmu_loader): """ err_msg = "Specified fmu path '.*\\' needs to contain a modelDescription.xml according to the FMI specification" with tempfile.TemporaryDirectory() as temp_dir: - with np.testing.assert_raises_regex(FMUException, err_msg): + with pytest.raises(FMUException, match = err_msg): fmu = fmu_loader(temp_dir, allow_unzipped_fmu = True) if assimulo_installed: class Test_FMUModelME1_Simulation: - @testattr(stddist = True) def test_simulate_with_debug_option_no_state(self): """ Verify that an instance of CVodeDebugInformation is created """ model = Dummy_FMUModelME1([], os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "NoState.Example1.fmu"), _connect_dll=False) @@ -90,7 +88,6 @@ def test_simulate_with_debug_option_no_state(self): from pyfmi.debug import CVodeDebugInformation debug = CVodeDebugInformation("NoState_Example1_debug.txt") - @testattr(stddist = True) def test_no_result(self): model = Dummy_FMUModelME1([], os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "NegatedAlias.fmu"), _connect_dll=False) @@ -98,7 +95,8 @@ def test_no_result(self): opts["result_handling"] = None res = model.simulate(options=opts) - nose.tools.assert_raises(Exception,res._get_result_data) + with pytest.raises(Exception): + res._get_result_data() model = Dummy_FMUModelME1([], os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "NegatedAlias.fmu"), _connect_dll=False) @@ -106,9 +104,9 @@ def test_no_result(self): opts["return_result"] = False res = model.simulate(options=opts) - nose.tools.assert_raises(Exception,res._get_result_data) + with pytest.raises(Exception): + res._get_result_data() - @testattr(stddist = True) def test_custom_result_handler(self): model = Dummy_FMUModelME1([], os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "NegatedAlias.fmu"), _connect_dll=False) @@ -120,11 +118,14 @@ def get_result(self): opts = model.simulate_options() opts["result_handling"] = "hejhej" - nose.tools.assert_raises(Exception, model.simulate, options=opts) + with pytest.raises(Exception): + model.simulate(options=opts) opts["result_handling"] = "custom" - nose.tools.assert_raises(Exception, model.simulate, options=opts) + with pytest.raises(Exception): + model.simulate(options=opts) opts["result_handler"] = A() - nose.tools.assert_raises(Exception, model.simulate, options=opts) + with pytest.raises(Exception): + model.simulate(options=opts) opts["result_handler"] = B() res = model.simulate(options=opts) @@ -136,7 +137,6 @@ def setup_atol_auto_update_test_base(self): opts["solver"] = "CVode" return model, opts - @testattr(stddist = True) def test_atol_auto_update1(self): """ Tests that atol automatically gets updated when "atol = factor * pre_init_nominals". @@ -148,7 +148,6 @@ def test_atol_auto_update1(self): model.simulate(options=opts, algorithm=NoSolveAlg) np.testing.assert_allclose(opts["CVode_options"]["atol"], [0.03, 0.03]) - @testattr(stddist = True) def test_atol_auto_update2(self): """ Tests that atol doesn't get auto-updated when heuristic fails. @@ -160,7 +159,6 @@ def test_atol_auto_update2(self): model.simulate(options=opts, algorithm=NoSolveAlg) np.testing.assert_allclose(opts["CVode_options"]["atol"], [0.03, 0.02]) - @testattr(stddist = True) def test_atol_auto_update3(self): """ Tests that atol doesn't get auto-updated when nominals are never retrieved. @@ -178,8 +176,6 @@ def test_atol_auto_update3(self): class Test_FMUModelME1: - - @testattr(stddist = True) def test_unzipped_fmu_exception_invalid_dir(self): """ Verify that we get an exception if unzipped FMU does not contain modelDescription.xml, which it should according to the FMI specification. """ _helper_unzipped_fmu_exception_invalid_dir(FMUModelME1) @@ -197,31 +193,26 @@ def _test_unzipped_bouncing_ball(self, fmu_loader): value = np.abs(res.final('h') - (0.0424044)) assert value < tol, "Assertion failed, value={} is not less than {}.".format(value, tol) - @testattr(stddist = True) def test_unzipped_fmu1(self): """ Test load and simulate unzipped ME FMU 1.0 using FMUModelME1 """ self._test_unzipped_bouncing_ball(FMUModelME1) - @testattr(stddist = True) def test_unzipped_fmu2(self): """ Test load and simulate unzipped ME FMU 1.0 using load_fmu """ self._test_unzipped_bouncing_ball(load_fmu) - @testattr(stddist = True) def test_invalid_binary(self): err_msg = "The FMU could not be loaded." fmu = os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "RLC_Circuit.fmu") - with nose.tools.assert_raises_regex(InvalidBinaryException, err_msg): + with pytest.raises(InvalidBinaryException, match = err_msg): model = FMUModelME1(fmu, _connect_dll=True) - @testattr(stddist = True) def test_invalid_version(self): err_msg = "This class only supports FMI 1.0" fmu = os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "LinearStability.SubSystem2.fmu") - with nose.tools.assert_raises_regex(InvalidVersionException, err_msg): + with pytest.raises(InvalidVersionException, match = err_msg): model = FMUModelME1(fmu, _connect_dll=True) - @testattr(stddist = True) def test_get_time_varying_variables(self): model = FMUModelME1(os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "RLC_Circuit.fmu"), _connect_dll=False) @@ -232,7 +223,6 @@ def test_get_time_varying_variables(self): assert len(i) == len(i_f) assert len(b) == len(b_f) - @testattr(stddist = True) def test_get_time_varying_variables_with_alias(self): model = FMUModelME1(os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "Alias1.fmu"), _connect_dll=False) @@ -241,20 +231,19 @@ def test_get_time_varying_variables_with_alias(self): assert len(r) == 1 assert r[0] == model.get_variable_valueref("y") - @testattr(stddist = True) def test_get_variable_by_valueref(self): bounce = FMUModelME1(os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "bouncingBall.fmu"), _connect_dll=False) assert "der(v)" == bounce.get_variable_by_valueref(3) assert "v" == bounce.get_variable_by_valueref(2) - nose.tools.assert_raises(FMUException, bounce.get_variable_by_valueref,7) + with pytest.raises(FMUException): + bounce.get_variable_by_valueref(7) - @testattr(stddist = True) def test_get_variable_nominal_valueref(self): bounce = FMUModelME1(os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "bouncingBall.fmu"), _connect_dll=False) assert bounce.get_variable_nominal("v") == bounce.get_variable_nominal(valueref=2) - @testattr(windows_full = True) + #@testattr(windows_full = True) def test_default_experiment(self): model = FMUModelME1(FMU_PATHS.ME1.coupled_clutches, _connect_dll=False) @@ -263,14 +252,12 @@ def test_default_experiment(self): assert np.abs(model.get_default_experiment_tolerance()-0.0001) < 1e-4 - @testattr(stddist = True) def test_log_file_name(self): model = FMUModelME1(os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "bouncingBall.fmu"), _connect_dll=False) assert os.path.exists("bouncingBall_log.txt") model = FMUModelME1(os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "bouncingBall.fmu"), _connect_dll=False, log_file_name="Test_log.txt") assert os.path.exists("Test_log.txt") - @testattr(stddist = True) def test_ode_get_sizes(self): bounce = FMUModelME1(os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "bouncingBall.fmu"), _connect_dll=False) dq = FMUModelME1(os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "dq.fmu"), _connect_dll=False) @@ -283,7 +270,6 @@ def test_ode_get_sizes(self): assert nCont == 1 assert nEvent == 0 - @testattr(stddist = True) def test_get_name(self): bounce = FMUModelME1(os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "bouncingBall.fmu"), _connect_dll=False) dq = FMUModelME1(os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "dq.fmu"), _connect_dll=False) @@ -291,14 +277,13 @@ def test_get_name(self): assert bounce.get_name() == 'bouncingBall' assert dq.get_name() == 'dq' - @testattr(stddist = True) def test_instantiate_jmu(self): """ Test that FMUModelME1 can not be instantiated with a JMU file. """ - nose.tools.assert_raises(FMUException,FMUModelME1,'model.jmu') + with pytest.raises(FMUException): + FMUModelME1('model.jmu') - @testattr(stddist = True) def test_get_fmi_options(self): """ Test that simulate_options on an FMU returns the correct options @@ -307,7 +292,6 @@ class instance. bounce = FMUModelME1(os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "bouncingBall.fmu"), _connect_dll=False) assert isinstance(bounce.simulate_options(), AssimuloFMIAlgOptions) - @testattr(stddist = True) def test_get_xxx_empty(self): """ Test that get_xxx([]) do not calls do not trigger calls to FMU. """ model = FMUModelME1(os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "bouncingBall.fmu"), _connect_dll=False) @@ -318,8 +302,6 @@ def test_get_xxx_empty(self): assert len(model.get_string([])) == 0, "get_string ([]) has non-empty return" class Test_FMUModelCS1: - - @testattr(stddist = True) def test_unzipped_fmu_exception_invalid_dir(self): """ Verify that we get an exception if unzipped FMU does not contain modelDescription.xml, which it should according to the FMI specification. """ _helper_unzipped_fmu_exception_invalid_dir(FMUModelCS1) @@ -337,31 +319,26 @@ def _test_unzipped_bouncing_ball(self, fmu_loader): value = np.abs(res.final('h') - (0.0424044)) assert value < tol, "Assertion failed, value={} is not less than {}.".format(value, tol) - @testattr(stddist = True) def test_unzipped_fmu1(self): """ Test load and simulate unzipped CS FMU 1.0 using FMUModelCS1 """ self._test_unzipped_bouncing_ball(FMUModelCS1) - @testattr(stddist = True) def test_unzipped_fmu2(self): """ Test load and simulate unzipped CS FMU 1.0 using load_fmu """ self._test_unzipped_bouncing_ball(load_fmu) - @testattr(stddist = True) def test_invalid_binary(self): err_msg = "The FMU could not be loaded." fmu = os.path.join(file_path, "files", "FMUs", "XML", "CS1.0", "NegatedAlias.fmu") - with nose.tools.assert_raises_regex(InvalidBinaryException, err_msg): + with pytest.raises(InvalidBinaryException, match = err_msg): model = FMUModelCS1(fmu, _connect_dll=True) - @testattr(stddist = True) def test_invalid_version(self): err_msg = "This class only supports FMI 1.0" fmu = os.path.join(file_path, "files", "FMUs", "XML", "CS2.0", "NegatedAlias.fmu") - with nose.tools.assert_raises_regex(InvalidVersionException, err_msg): + with pytest.raises(InvalidVersionException, match = err_msg): model = FMUModelCS1(fmu, _connect_dll=True) - @testattr(stddist = True) def test_custom_result_handler(self): model = Dummy_FMUModelCS1([], os.path.join(file_path, "files", "FMUs", "XML", "CS1.0", "NegatedAlias.fmu"), _connect_dll=False) @@ -373,15 +350,17 @@ def get_result(self): opts = model.simulate_options() opts["result_handling"] = "hejhej" - nose.tools.assert_raises(Exception, model.simulate, options=opts) + with pytest.raises(Exception): + model.simulate(options=opts) opts["result_handling"] = "custom" - nose.tools.assert_raises(Exception, model.simulate, options=opts) + with pytest.raises(Exception): + model.simulate(options=opts) opts["result_handler"] = A() - nose.tools.assert_raises(Exception, model.simulate, options=opts) + with pytest.raises(Exception): + model.simulate(options=opts) opts["result_handler"] = B() res = model.simulate(options=opts) - @testattr(stddist = True) def test_no_result(self): model = Dummy_FMUModelCS1([], os.path.join(file_path, "files", "FMUs", "XML", "CS1.0", "NegatedAlias.fmu"), _connect_dll=False) @@ -389,7 +368,8 @@ def test_no_result(self): opts["result_handling"] = None res = model.simulate(options=opts) - nose.tools.assert_raises(Exception,res._get_result_data) + with pytest.raises(Exception): + res._get_result_data() model = Dummy_FMUModelCS1([], os.path.join(file_path, "files", "FMUs", "XML", "CS1.0", "NegatedAlias.fmu"), _connect_dll=False) @@ -397,9 +377,9 @@ def test_no_result(self): opts["return_result"] = False res = model.simulate(options=opts) - nose.tools.assert_raises(Exception,res._get_result_data) + with pytest.raises(Exception): + res._get_result_data() - @testattr(stddist = True) def test_result_name_file(self): model = Dummy_FMUModelCS1([], os.path.join(file_path, "files", "FMUs", "XML", "CS1.0", "CoupledClutches.fmu"), _connect_dll=False) @@ -417,7 +397,6 @@ def test_result_name_file(self): assert res.result_file == "CoupledClutches_result_test.txt" assert os.path.exists(res.result_file) - @testattr(stddist = True) def test_default_experiment(self): model = FMUModelCS1(os.path.join(file_path, "files", "FMUs", "XML", "CS1.0", "CoupledClutches.fmu"), _connect_dll=False) @@ -425,25 +404,24 @@ def test_default_experiment(self): assert np.abs(model.get_default_experiment_stop_time()-1.5) < 1e-4 assert np.abs(model.get_default_experiment_tolerance()-0.0001) < 1e-4 - @testattr(stddist = True) def test_log_file_name(self): model = FMUModelCS1(os.path.join(file_path, "files", "FMUs", "XML", "CS1.0", "bouncingBall.fmu", ), _connect_dll=False) assert os.path.exists("bouncingBall_log.txt") model = FMUModelCS1(os.path.join(file_path, "files", "FMUs", "XML", "CS1.0", "bouncingBall.fmu"), _connect_dll=False, log_file_name="Test_log.txt") assert os.path.exists("Test_log.txt") - @testattr(stddist = True) def test_erreneous_ncp(self): model = Dummy_FMUModelCS1([], os.path.join(file_path, "files", "FMUs", "XML", "CS1.0", "NegatedAlias.fmu"), _connect_dll=False) opts = model.simulate_options() opts["ncp"] = 0 - nose.tools.assert_raises(FMUException, model.simulate, options=opts) + with pytest.raises(FMUException): + model.simulate(options=opts) opts["ncp"] = -1 - nose.tools.assert_raises(FMUException, model.simulate, options=opts) + with pytest.raises(FMUException): + model.simulate(options=opts) class Test_FMUModelBase: - @testattr(stddist = True) def test_unicode_description(self): full_path = os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "Description.fmu") model = FMUModelME1(full_path, _connect_dll=False) @@ -452,14 +430,12 @@ def test_unicode_description(self): assert desc == "Test symbols '' ‘’" - @testattr(stddist = True) def test_get_erronous_nominals(self): model = FMUModelME1(FMU_PATHS.ME1.nominal_test4, _connect_dll=False) - nose.tools.assert_almost_equal(model.get_variable_nominal("x"), 2.0) - nose.tools.assert_almost_equal(model.get_variable_nominal("y"), 1.0) + assert model.get_variable_nominal("x") == pytest.approx(2.0) + assert model.get_variable_nominal("y") == pytest.approx(1.0) - @testattr(stddist = True) def test_caching(self): negated_alias = FMUModelME1(os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "NegatedAlias.fmu"), _connect_dll=False) @@ -487,7 +463,6 @@ def test_caching(self): vars_6 = negated_alias.get_model_variables() assert id(vars_1) != id(vars_6) - @testattr(stddist = True) def test_get_scalar_variable(self): negated_alias = FMUModelME1(os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "NegatedAlias.fmu"), _connect_dll=False) @@ -500,26 +475,27 @@ def test_get_scalar_variable(self): assert sc_x.causality == fmi.FMI_INTERNAL assert sc_x.alias == fmi.FMI_NO_ALIAS - nose.tools.assert_raises(FMUException, negated_alias.get_scalar_variable, "not_existing") + with pytest.raises(FMUException): + negated_alias.get_scalar_variable("not_existing") - @testattr(stddist = True) def test_get_variable_description(self): model = FMUModelME1(FMU_PATHS.ME1.coupled_clutches, _connect_dll=False) assert model.get_variable_description("J1.phi") == "Absolute rotation angle of component" - @testattr(stddist = True) def test_simulation_without_initialization(self): model = Dummy_FMUModelME1([], os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "bouncingBall.fmu"), _connect_dll=False) opts = model.simulate_options() opts["initialize"] = False - nose.tools.assert_raises(FMUException, model.simulate, options=opts) + with pytest.raises(FMUException): + model.simulate(options=opts) model = Dummy_FMUModelCS1([], os.path.join(file_path, "files", "FMUs", "XML", "CS1.0", "bouncingBall.fmu"), _connect_dll=False) opts = model.simulate_options() opts["initialize"] = False - nose.tools.assert_raises(FMUException, model.simulate, options=opts) + with pytest.raises(FMUException): + model.simulate(options=opts) def test_get_erroneous_nominals_capi_fmi1(self): """ Tests that erroneous nominals returned from getting nominals of continuous states get auto-corrected. """ @@ -549,30 +525,26 @@ def test_get_erroneous_nominals_capi_fmi1(self): expected_msg2 = "The nominal value for J4.w is 0.0 which is illegal according to the " \ + "FMI specification. Setting the nominal to 1.0." log = str(log_stream.getvalue()) - nose.tools.assert_in(expected_msg1, log) # First warning of 6. - nose.tools.assert_in(expected_msg2, log) # Last warning of 6. + assert expected_msg1 in log # First warning of 6. + assert expected_msg2 in log # Last warning of 6. # Check values are auto-corrected: - nose.tools.assert_almost_equal(xn[0], 2.0) # -2.0 - nose.tools.assert_almost_equal(xn[1], 1.0) # 0.0 - nose.tools.assert_almost_equal(xn[2], 2.0) # 2.0 - nose.tools.assert_almost_equal(xn[3], 2.0) # -2.0 - nose.tools.assert_almost_equal(xn[4], 1.0) # 0.0 - nose.tools.assert_almost_equal(xn[5], 2.0) # 2.0 - nose.tools.assert_almost_equal(xn[6], 2.0) # -2.0 - nose.tools.assert_almost_equal(xn[7], 1.0) # 0,0 + assert xn[0] == pytest.approx(2.0) + assert xn[1] == pytest.approx(1.0) + assert xn[2] == pytest.approx(2.0) + assert xn[3] == pytest.approx(2.0) + assert xn[4] == pytest.approx(1.0) + assert xn[5] == pytest.approx(2.0) + assert xn[6] == pytest.approx(2.0) + assert xn[7] == pytest.approx(1.0) class Test_LoadFMU: - - @testattr(stddist = True) def test_unzipped_fmu_exception_invalid_dir(self): """ Verify that we get an exception if unzipped FMU does not contain modelDescription.xml, which it should according to the FMI specification. """ _helper_unzipped_fmu_exception_invalid_dir(load_fmu) class Test_FMUModelCS2: - - @testattr(stddist = True) def test_unzipped_fmu_exception_invalid_dir(self): """ Verify that we get an exception if unzipped FMU does not contain modelDescription.xml, which it should according to the FMI specification. """ _helper_unzipped_fmu_exception_invalid_dir(FMUModelCS2) @@ -590,17 +562,14 @@ def _test_unzipped_bouncing_ball(self, fmu_loader): value = np.abs(res.final('h') - (0.0424044)) assert value < tol, "Assertion failed, value={} is not less than {}.".format(value, tol) - @testattr(stddist = True) def test_unzipped_fmu1(self): """ Test load and simulate unzipped CS FMU 2.0 using FMUModelCS2 """ self._test_unzipped_bouncing_ball(FMUModelCS2) - @testattr(stddist = True) def test_unzipped_fmu2(self): """ Test load and simulate unzipped CS FMU 2.0 using load_fmu """ self._test_unzipped_bouncing_ball(load_fmu) - @testattr(stddist = True) def test_log_file_name(self): full_path = os.path.join(file_path, "files", "FMUs", "XML", "CS2.0", "CoupledClutches.fmu") model = FMUModelCS2(full_path, _connect_dll=False) @@ -608,40 +577,37 @@ def test_log_file_name(self): path, file_name = os.path.split(full_path) assert model.get_log_filename() == file_name.replace(".","_")[:-4]+"_log.txt" - @testattr(stddist = True) def test_invalid_binary(self): err_msg = "The FMU could not be loaded." fmu = os.path.join(file_path, "files", "FMUs", "XML", "CS2.0", "CoupledClutches.fmu") - with nose.tools.assert_raises_regex(InvalidBinaryException, err_msg): + with pytest.raises(InvalidBinaryException, match = err_msg): model = FMUModelCS2(fmu, _connect_dll=True) - @testattr(stddist = True) def test_invalid_version(self): err_msg = "The FMU version is not supported" fmu = os.path.join(file_path, "files", "FMUs", "XML", "CS1.0", "CoupledClutches.fmu") - with nose.tools.assert_raises_regex(InvalidVersionException, err_msg): + with pytest.raises(InvalidVersionException, match = err_msg): model = FMUModelCS2(fmu, _connect_dll=True) - @testattr(stddist = True) def test_unzipped_fmu_exceptions(self): """ Verify exception is raised if 'fmu' is a file and allow_unzipped_fmu is set to True, with FMUModelCS2. """ err_msg = "Argument named 'fmu' must be a directory if argument 'allow_unzipped_fmu' is set to True." - with nose.tools.assert_raises_regex(FMUException, err_msg): + with pytest.raises(FMUException, match = err_msg): model = FMUModelCS2(os.path.join(file_path, "files", "FMUs", "XML", "CS2.0", "LinearStability.SubSystem1.fmu"), _connect_dll=False, allow_unzipped_fmu=True) - @testattr(stddist = True) def test_erreneous_ncp(self): model = FMUModelCS2(os.path.join(file_path, "files", "FMUs", "XML", "CS2.0", "CoupledClutches.fmu"), _connect_dll=False) opts = model.simulate_options() opts["ncp"] = 0 - nose.tools.assert_raises(FMUException, model.simulate, options=opts) + with pytest.raises(FMUException): + model.simulate(options=opts) opts["ncp"] = -1 - nose.tools.assert_raises(FMUException, model.simulate, options=opts) + with pytest.raises(FMUException): + model.simulate(options=opts) if assimulo_installed: class Test_FMUModelME2_Simulation: - @testattr(stddist = True) def test_basicsens1(self): #Noncompliant FMI test as 'd' is parameter is not supposed to be able to be set during simulation model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "BasicSens1.fmu"), _connect_dll=False) @@ -658,11 +624,10 @@ def f(*args, **kwargs): opts["sensitivities"] = ["d"] res = model.simulate(options=opts) - nose.tools.assert_almost_equal(res.final('dx/dd'), 0.36789, 3) + assert res.final('dx/dd') == pytest.approx(0.36789, abs = 1e-3) assert res.solver.statistics["nsensfcnfcns"] > 0 - @testattr(stddist = True) def test_basicsens1dir(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "BasicSens1.fmu"), _connect_dll=False) @@ -690,12 +655,11 @@ def d(*args, **kwargs): opts["sensitivities"] = ["d"] res = model.simulate(options=opts) - nose.tools.assert_almost_equal(res.final('dx/dd'), 0.36789, 3) + assert res.final('dx/dd') == pytest.approx(0.36789, abs = 1e-3) assert res.solver.statistics["nsensfcnfcns"] > 0 assert res.solver.statistics["nfcnjacs"] == 0 - @testattr(stddist = True) def test_basicsens2(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "BasicSens2.fmu"), _connect_dll=False) @@ -723,11 +687,10 @@ def d(*args, **kwargs): opts["sensitivities"] = ["d"] res = model.simulate(options=opts) - nose.tools.assert_almost_equal(res.final('dx/dd'), 0.36789, 3) + assert res.final('dx/dd') == pytest.approx(0.36789, abs = 1e-3) assert res.solver.statistics["nsensfcnfcns"] == 0 - @testattr(stddist = True) def test_relative_tolerance(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "NoState.Example1.fmu"), _connect_dll=False) @@ -738,7 +701,6 @@ def test_relative_tolerance(self): assert res.options["CVode_options"]["atol"] == 1e-10 - @testattr(stddist = True) def test_simulate_with_debug_option_no_state(self): """ Verify that an instance of CVodeDebugInformation is created """ model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "NoState.Example1.fmu"), _connect_dll=False) @@ -753,7 +715,6 @@ def test_simulate_with_debug_option_no_state(self): from pyfmi.debug import CVodeDebugInformation debug = CVodeDebugInformation("NoState_Example1_debug.txt") - @testattr(stddist = True) def test_maxord_is_set(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "NoState.Example1.fmu"), _connect_dll=False) opts = model.simulate_options() @@ -764,7 +725,6 @@ def test_maxord_is_set(self): assert res.solver.maxord == 1 - @testattr(stddist = True) def test_with_jacobian_option(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "NoState.Example1.fmu"), _connect_dll=False) opts = model.simulate_options() @@ -793,7 +753,6 @@ def run_case(expected, default="Default"): opts["with_jacobian"] = True run_case(True, True) - @testattr(stddist = True) def test_sparse_option(self): def run_case(expected_jacobian, expected_sparse, fnbr=0, nnz={}, set_sparse=False): @@ -819,13 +778,11 @@ def get_derivatives_dependencies(self): run_case(True, "SPARSE", PYFMI_JACOBIAN_SPARSE_SIZE_LIMIT+1, {"Dep": [1]*PYFMI_JACOBIAN_SPARSE_SIZE_LIMIT}) run_case(True, "SPARSE", PYFMI_JACOBIAN_SPARSE_SIZE_LIMIT+1, {"Dep": [1]*PYFMI_JACOBIAN_SPARSE_SIZE_LIMIT}, True) - @testattr(stddist = True) def test_ncp_option(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "NoState.Example1.fmu"), _connect_dll=False) opts = model.simulate_options() assert opts["ncp"] == 500, opts["ncp"] - @testattr(stddist = True) def test_solver_options(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "NoState.Example1.fmu"), _connect_dll=False) opts = model.simulate_options() @@ -840,7 +797,6 @@ def test_solver_options(self): assert opts["CVode_options"]["atol"] == "Default", "Default should have been changed: " + opts["CVode_options"]["atol"] assert opts["CVode_options"]["maxh"] == 1.0, "Value should have been changed to 1.0: " + opts["CVode_options"]["maxh"] - @testattr(stddist = True) def test_solver_options_using_defaults(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "NoState.Example1.fmu"), _connect_dll=False) opts = model.simulate_options() @@ -853,7 +809,6 @@ def test_solver_options_using_defaults(self): assert opts["CVode_options"]["atol"] == 1e-6, "Default should have been changed: " + opts["CVode_options"]["atol"] assert opts["CVode_options"]["maxh"] == "Default", "Value should have been default is: " + opts["CVode_options"]["maxh"] - @testattr(stddist = True) def test_deepcopy_option(self): opts = AssimuloFMIAlgOptions() opts["CVode_options"]["maxh"] = 2.0 @@ -864,7 +819,6 @@ def test_deepcopy_option(self): assert opts["CVode_options"]["maxh"] == opts_copy["CVode_options"]["maxh"], "Deepcopy not working..." - @testattr(stddist = True) def test_maxh_option(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "NoState.Example1.fmu"), _connect_dll=False) opts = model.simulate_options() @@ -895,7 +849,6 @@ def run_case(tstart, tstop, solver, ncp="Default"): run_case(0,1,"LSODAR") run_case(0,1,"LSODAR") - @testattr(stddist = True) def test_rtol_auto_update(self): """ Test that default rtol picks up the unbounded attribute. """ model = Dummy_FMUModelME2([], FMU_PATHS.ME2.coupled_clutches_modified, _connect_dll=False) @@ -907,13 +860,12 @@ def test_rtol_auto_update(self): if res.solver.supports.get('rtol_as_vector', False): # automatic construction of rtol vector if model.get_variable_unbounded(state): - nose.tools.assert_equal(res.solver.rtol[i], 0) + assert res.solver.rtol[i] == 0 else: - nose.tools.assert_greater(res.solver.rtol[i], 0) + assert res.solver.rtol[i] > 0 else: # no support: scalar rtol - nose.tools.assert_true(isinstance(res.solver.rtol, float)) + assert isinstance(res.solver.rtol, float) - @testattr(stddist = True) def test_rtol_vector_manual_valid(self): """ Tests manual valid rtol vector works; if supported. """ @@ -925,12 +877,11 @@ def test_rtol_vector_manual_valid(self): try: res = model.simulate(options=opts) # solver support - nose.tools.assert_equal(res.solver.rtol[0], 1e-5) - nose.tools.assert_equal(res.solver.rtol[1], 0.) + assert res.solver.rtol[0] == 1e-5 + assert res.solver.rtol[1] == 0. except InvalidOptionException as e: # if no solver support - nose.tools.assert_true(str(e).startswith("Failed to set the solver option 'rtol'")) + assert str(e).startswith("Failed to set the solver option 'rtol'") - @testattr(stddist = True) def test_rtol_vector_manual_size_mismatch(self): """ Tests invalid rtol vector: size mismatch. """ model = Dummy_FMUModelME2([], FMU_PATHS.ME2.nominal_test4, _connect_dll=False) @@ -939,10 +890,9 @@ def test_rtol_vector_manual_size_mismatch(self): opts["CVode_options"]["rtol"] = [1e-5, 0, 1e-5] err_msg = "If the relative tolerance is provided as a vector, it need to be equal to the number of states." - with nose.tools.assert_raises_regex(InvalidOptionException, err_msg): + with pytest.raises(InvalidOptionException, match = err_msg): model.simulate(options=opts) - @testattr(stddist = True) def test_rtol_vector_manual_invalid(self): """ Tests invalid rtol vector: different nonzero values. """ @@ -952,10 +902,9 @@ def test_rtol_vector_manual_invalid(self): opts["CVode_options"]["rtol"] = [1e-5, 0, 1e-5, 1e-5, 0, 1e-5,1e-6, 0] err_msg = "If the relative tolerance is provided as a vector, the values need to be equal except for zeros." - with nose.tools.assert_raises_regex(InvalidOptionException, err_msg): + with pytest.raises(InvalidOptionException, match = err_msg): model.simulate(options=opts) - @testattr(stddist = True) def test_rtol_vector_manual_scalar_conversion(self): """ Test automatic scalar conversion of trivial rtol vector. """ model = Dummy_FMUModelME2([], FMU_PATHS.ME2.nominal_test4, _connect_dll=False) @@ -965,9 +914,8 @@ def test_rtol_vector_manual_scalar_conversion(self): #Verify no exception is raised as the rtol vector should be treated as a scalar res = model.simulate(options=opts) - nose.tools.assert_equal(res.solver.rtol, 1e-5) + assert res.solver.rtol == 1e-5 - @testattr(stddist = True) def test_rtol_vector_unsupported(self): """ Test that rtol as a vector triggers exceptions for unsupported solvers. """ model = Dummy_FMUModelME2([], FMU_PATHS.ME2.nominal_test4, _connect_dll=False) @@ -983,10 +931,10 @@ def run_case(solver): try: res = model.simulate(options=opts) # solver support; check tolerances - nose.tools.assert_equal(res.solver.rtol[0], 1e-5) - nose.tools.assert_equal(res.solver.rtol[1], 0.0) + assert res.solver.rtol[0] == 1e-5 + assert res.solver.rtol[1] == 0.0 except InvalidOptionException as e: - nose.tools.assert_true(str(e).startswith("Failed to set the solver option 'rtol'")) + assert str(e).startswith("Failed to set the solver option 'rtol'") return # OK run_case("CVode") @@ -1003,7 +951,6 @@ def setup_atol_auto_update_test_base(self): opts["solver"] = "CVode" return model, opts - @testattr(stddist = True) def test_atol_auto_update1(self): """ Tests that atol automatically gets updated when "atol = factor * pre_init_nominals". @@ -1015,7 +962,6 @@ def test_atol_auto_update1(self): model.simulate(options=opts, algorithm=NoSolveAlg) np.testing.assert_allclose(opts["CVode_options"]["atol"], [0.03, 0.03]) - @testattr(stddist = True) def test_atol_auto_update2(self): """ Tests that atol doesn't get auto-updated when heuristic fails. @@ -1027,7 +973,6 @@ def test_atol_auto_update2(self): model.simulate(options=opts, algorithm=NoSolveAlg) np.testing.assert_allclose(opts["CVode_options"]["atol"], [0.03, 0.02]) - @testattr(stddist = True) def test_atol_auto_update3(self): """ Tests that atol doesn't get auto-updated when nominals are never retrieved. @@ -1039,7 +984,6 @@ def test_atol_auto_update3(self): model.simulate(options=opts, algorithm=NoSolveAlg) np.testing.assert_allclose(opts["CVode_options"]["atol"], [0.02, 0.01]) - @testattr(stddist = True) def test_atol_auto_update4(self): """ Tests that atol is not auto-updated when it's set the "correct" way (post initialization). @@ -1054,7 +998,6 @@ def test_atol_auto_update4(self): model.simulate(options=opts, algorithm=NoSolveAlg) np.testing.assert_allclose(opts["CVode_options"]["atol"], [0.03, 0.03]) - @testattr(stddist = True) def test_atol_auto_update5(self): """ Tests that atol is automatically set and depends on rtol. @@ -1065,7 +1008,6 @@ def test_atol_auto_update5(self): model.simulate(options=opts, algorithm=NoSolveAlg) np.testing.assert_allclose(opts["CVode_options"]["atol"], [3e-8, 3e-8]) - @testattr(stddist = True) def test_atol_auto_update6(self): """ Tests that rtol doesn't affect explicitly set atol. @@ -1080,8 +1022,6 @@ def test_atol_auto_update6(self): class Test_FMUModelME2: - - @testattr(stddist = True) def test_unzipped_fmu_exception_invalid_dir(self): """ Verify that we get an exception if unzipped FMU does not contain modelDescription.xml, which it should according to the FMI specification. """ _helper_unzipped_fmu_exception_invalid_dir(FMUModelME2) @@ -1099,36 +1039,30 @@ def _test_unzipped_bouncing_ball(self, fmu_loader): value = np.abs(res.final('h') - (0.0424044)) assert value < tol, "Assertion failed, value={} is not less than {}.".format(value, tol) - @testattr(stddist = True) def test_unzipped_fmu1(self): """ Test load and simulate unzipped ME FMU 2.0 using FMUModelME2 """ self._test_unzipped_bouncing_ball(FMUModelME2) - @testattr(stddist = True) def test_unzipped_fmu2(self): """ Test load and simulate unzipped ME FMU 2.0 using load_fmu """ self._test_unzipped_bouncing_ball(load_fmu) - @testattr(stddist = True) def test_unzipped_fmu_exceptions(self): """ Verify exception is raised if 'fmu' is a file and allow_unzipped_fmu is set to True, with FMUModelME2. """ err_msg = "Argument named 'fmu' must be a directory if argument 'allow_unzipped_fmu' is set to True." - with nose.tools.assert_raises_regex(FMUException, err_msg): + with pytest.raises(FMUException, match = err_msg): model = FMUModelME2(os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "LinearStability.SubSystem2.fmu"), _connect_dll=False, allow_unzipped_fmu=True) - @testattr(stddist = True) def test_invalid_binary(self): err_msg = "The FMU could not be loaded." - with nose.tools.assert_raises_regex(InvalidBinaryException, err_msg): + with pytest.raises(InvalidBinaryException, match = err_msg): model = FMUModelME2(os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "LinearStability.SubSystem2.fmu"), _connect_dll=True) - @testattr(stddist = True) def test_invalid_version(self): err_msg = "The FMU version is not supported by this class" - with nose.tools.assert_raises_regex(InvalidVersionException, err_msg): + with pytest.raises(InvalidVersionException, match = err_msg): model = FMUModelME2(os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "RLC_Circuit.fmu"), _connect_dll=True) - @testattr(stddist = True) def test_estimate_directional_derivatives_linearstate(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "LinearStateSpace.fmu"), _connect_dll=False) @@ -1158,7 +1092,6 @@ def f(*args, **kwargs): assert np.allclose(Cs, C.toarray()), str(Cs)+' '+str(C.toarray()) assert np.allclose(Ds, D.toarray()), str(Ds)+' '+str(D.toarray()) - @testattr(stddist = True) def test_estimate_directional_derivatives_without_structure_info(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "Bouncing_Ball.fmu"), _connect_dll=False) @@ -1186,7 +1119,6 @@ def f(*args, **kwargs): assert np.allclose(Cs, C.toarray()), str(Cs)+' '+str(C.toarray()) assert np.allclose(Ds, D.toarray()), str(Ds)+' '+str(D.toarray()) - @testattr(stddist = True) def test_estimate_directional_derivatives_BCD(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "OutputTest2.fmu"), _connect_dll=False) @@ -1242,7 +1174,6 @@ def f(*args, **kwargs): assert np.allclose(C, np.array([[0.0, 0.0], [0.0, 1.0], [1.0, 0.0]])), str(C.toarray()) assert np.allclose(D, np.array([[-1.0], [0.0], [1.0]])), str(D.toarray()) - @testattr(stddist = True) def test_output_dependencies(self): model = FMUModelME2(os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "OutputTest2.fmu"), _connect_dll=False) @@ -1256,7 +1187,6 @@ def test_output_dependencies(self): assert input_dep["y3"][0] == "u1" assert len(input_dep["y2"]) == 0 - @testattr(stddist = True) def test_output_dependencies_2(self): model = FMUModelME2(FMU_PATHS.ME2.coupled_clutches, _connect_dll=False) @@ -1265,7 +1195,6 @@ def test_output_dependencies_2(self): assert len(state_dep.keys()) == 0, len(state_dep.keys()) assert len(input_dep.keys()) == 0, len(input_dep.keys()) - @testattr(stddist = True) def test_derivative_dependencies(self): model = FMUModelME2(os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "NoState.Example1.fmu"), _connect_dll=False) @@ -1274,7 +1203,6 @@ def test_derivative_dependencies(self): assert len(state_dep.keys()) == 0, len(state_dep.keys()) assert len(input_dep.keys()) == 0, len(input_dep.keys()) - @testattr(stddist = True) def test_exception_with_load_fmu(self): """ Verify exception is raised. """ err_msg = "Argument named 'fmu' must be a directory if argument 'allow_unzipped_fmu' is set to True." @@ -1284,16 +1212,15 @@ def test_exception_with_load_fmu(self): with open(test_file, 'w') as fh: fh.write('') rm_file = True - with nose.tools.assert_raises_regex(FMUException, err_msg): + with pytest.raises(FMUException, match = err_msg): fmu = load_fmu(test_file, allow_unzipped_fmu = True) if rm_file: os.remove(test_file) - @testattr(stddist = True) def test_malformed_xml(self): - nose.tools.assert_raises(InvalidXMLException, load_fmu, os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "MalFormed.fmu")) + with pytest.raises(InvalidXMLException): + load_fmu(os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "MalFormed.fmu")) - @testattr(stddist = True) def test_log_file_name(self): full_path = FMU_PATHS.ME2.coupled_clutches @@ -1302,25 +1229,26 @@ def test_log_file_name(self): path, file_name = os.path.split(full_path) assert model.get_log_filename() == file_name.replace(".","_")[:-4]+"_log.txt" - @testattr(stddist = True) def test_units(self): model = FMUModelME2(FMU_PATHS.ME2.coupled_clutches, _connect_dll=False) assert model.get_variable_unit("J1.w") == "rad/s", model.get_variable_unit("J1.w") assert model.get_variable_unit("J1.phi") == "rad", model.get_variable_unit("J1.phi") - nose.tools.assert_raises(FMUException, model.get_variable_unit, "clutch1.useHeatPort") - nose.tools.assert_raises(FMUException, model.get_variable_unit, "clutch1.sss") - nose.tools.assert_raises(FMUException, model.get_variable_unit, "clutch1.sss") + with pytest.raises(FMUException): + model.get_variable_unit("clutch1.useHeatPort") + with pytest.raises(FMUException): + model.get_variable_unit("clutch1.sss") + with pytest.raises(FMUException): + model.get_variable_unit("clutch1.sss") - @testattr(stddist = True) def test_display_units(self): model = FMUModelME2(FMU_PATHS.ME2.coupled_clutches, _connect_dll=False) assert model.get_variable_display_unit("J1.phi") == "deg", model.get_variable_display_unit("J1.phi") - nose.tools.assert_raises(FMUException, model.get_variable_display_unit, "J1.w") + with pytest.raises(FMUException): + model.get_variable_display_unit("J1.w") - @testattr(stddist = True) def test_get_xxx_empty(self): """ Test that get_xxx([]) do not calls do not trigger calls to FMU. """ model = FMUModelME2(os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "bouncingBall.fmu"), _connect_dll=False) @@ -1331,8 +1259,6 @@ def test_get_xxx_empty(self): assert len(model.get_string([])) == 0, "get_string ([]) has non-empty return" class Test_FMUModelBase2: - - @testattr(stddist = True) def test_relative_quantity(self): model = FMUModelME2(os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "test_type_definitions.fmu"), _connect_dll=False) @@ -1347,9 +1273,9 @@ def test_relative_quantity(self): rel = model.get_variable_relative_quantity("real_with_typedef") assert rel is True, "Relative quantity should be True" - nose.tools.assert_raises(FMUException, model.get_variable_relative_quantity, "int_with_attr") + with pytest.raises(FMUException): + model.get_variable_relative_quantity("int_with_attr") - @testattr(stddist = True) def test_unbounded_attribute(self): model = FMUModelME2(os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "test_type_definitions.fmu"), _connect_dll=False) @@ -1364,9 +1290,9 @@ def test_unbounded_attribute(self): unbounded = model.get_variable_unbounded("real_with_typedef") assert unbounded is True, "Unbounded should be True" - nose.tools.assert_raises(FMUException, model.get_variable_unbounded, "int_with_attr") + with pytest.raises(FMUException): + model.get_variable_unbounded("int_with_attr") - @testattr(stddist = True) def test_unicode_description(self): model = FMUModelME2(os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "Description.fmu"), _connect_dll=False) @@ -1374,7 +1300,6 @@ def test_unicode_description(self): assert desc == "Test symbols '' ‘’" - @testattr(stddist = True) def test_declared_enumeration_type(self): model = FMUModelME2(os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "Enumerations.Enumeration3.fmu"), _connect_dll=False) @@ -1387,26 +1312,26 @@ def test_declared_enumeration_type(self): assert enum.name == "Enumerations.Enumeration3.cities", "Got: " + enum.name assert enum.description == "", "Got: " + enum.description - nose.tools.assert_raises(FMUException, model.get_variable_declared_type, "z") + with pytest.raises(FMUException): + model.get_variable_declared_type("z") - @testattr(stddist = True) def test_get_erroneous_nominals_xml(self): model = FMUModelME2(FMU_PATHS.ME2.nominal_test4, _connect_dll=False) - nose.tools.assert_almost_equal(model.get_variable_nominal("x"), 2.0) - nose.tools.assert_almost_equal(model.get_variable_nominal("y"), 1.0) + assert model.get_variable_nominal("x") == pytest.approx(2.0) + assert model.get_variable_nominal("y") == pytest.approx(1.0) - nose.tools.assert_almost_equal(model.get_variable_nominal("x", _override_erroneous_nominal=False), -2.0) - nose.tools.assert_almost_equal(model.get_variable_nominal("y", _override_erroneous_nominal=False), 0.0) + assert model.get_variable_nominal("x", _override_erroneous_nominal=False) == pytest.approx(-2.0) + assert model.get_variable_nominal("y", _override_erroneous_nominal=False) == pytest.approx(0.0) x_vref = model.get_variable_valueref("x") y_vref = model.get_variable_valueref("y") - nose.tools.assert_almost_equal(model.get_variable_nominal(valueref=x_vref), 2.0) - nose.tools.assert_almost_equal(model.get_variable_nominal(valueref=y_vref), 1.0) + assert model.get_variable_nominal(valueref=x_vref) == pytest.approx(2.0) + assert model.get_variable_nominal(valueref=y_vref) == pytest.approx(1.0) - nose.tools.assert_almost_equal(model.get_variable_nominal(valueref=x_vref, _override_erroneous_nominal=False), -2.0) - nose.tools.assert_almost_equal(model.get_variable_nominal(valueref=y_vref, _override_erroneous_nominal=False), 0.0) + assert model.get_variable_nominal(valueref=x_vref, _override_erroneous_nominal=False) == pytest.approx(-2.0) + assert model.get_variable_nominal(valueref=y_vref, _override_erroneous_nominal=False) == pytest.approx(0.0) def test_get_erroneous_nominals_capi(self): """ Tests that erroneous nominals returned from GetNominalsOfContinuousStates get auto-corrected. """ @@ -1435,20 +1360,19 @@ def test_get_erroneous_nominals_capi(self): expected_msg2 = "The nominal value for J4.w is 0.0 which is illegal according to the " \ + "FMI specification. Setting the nominal to 1.0." log = str(log_stream.getvalue()) - nose.tools.assert_in(expected_msg1, log) # First warning of 6. - nose.tools.assert_in(expected_msg2, log) # Last warning of 6. + assert expected_msg1 in log # First warning of 6. + assert expected_msg2 in log # Last warning of 6. # Check that values are auto-corrected: - nose.tools.assert_almost_equal(xn[0], 2.0) # -2.0 - nose.tools.assert_almost_equal(xn[1], 1.0) # 0.0 - nose.tools.assert_almost_equal(xn[2], 2.0) # 2.0 - nose.tools.assert_almost_equal(xn[3], 2.0) # -2.0 - nose.tools.assert_almost_equal(xn[4], 1.0) # 0.0 - nose.tools.assert_almost_equal(xn[5], 2.0) # 2.0 - nose.tools.assert_almost_equal(xn[6], 2.0) # -2.0 - nose.tools.assert_almost_equal(xn[7], 1.0) # 0,0 - - @testattr(stddist = True) + assert xn[0] == pytest.approx(2.0) + assert xn[1] == pytest.approx(1.0) + assert xn[2] == pytest.approx(2.0) + assert xn[3] == pytest.approx(2.0) + assert xn[4] == pytest.approx(1.0) + assert xn[5] == pytest.approx(2.0) + assert xn[6] == pytest.approx(2.0) + assert xn[7] == pytest.approx(1.0) + def test_get_time_varying_variables(self): model = FMUModelME2(FMU_PATHS.ME2.coupled_clutches, _connect_dll=False) @@ -1467,38 +1391,39 @@ def test_get_time_varying_variables(self): [r,i,b] = model.get_model_time_varying_value_references(filter=list(vars.keys())) assert len(r) == 1, len(r) - @testattr(stddist = True) def test_get_directional_derivative_capability(self): bounce = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "bouncingBall.fmu"), _connect_dll=False) bounce.setup_experiment() bounce.initialize() # Bouncing ball don't have the capability, check that this is handled - nose.tools.assert_raises(FMUException, bounce.get_directional_derivative, [1], [1], [1]) + with pytest.raises(FMUException): + bounce.get_directional_derivative([1], [1], [1]) bounce = Dummy_FMUModelCS2([], os.path.join(file_path, "files", "FMUs", "XML", "CS2.0", "bouncingBall.fmu"), _connect_dll=False) bounce.setup_experiment() bounce.initialize() # Bouncing ball don't have the capability, check that this is handled - nose.tools.assert_raises(FMUException, bounce.get_directional_derivative, [1], [1], [1]) + with pytest.raises(FMUException): + bounce.get_directional_derivative([1], [1], [1]) - @testattr(stddist = True) def test_simulation_without_initialization(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "bouncingBall.fmu"), _connect_dll=False) opts = model.simulate_options() opts["initialize"] = False - nose.tools.assert_raises(FMUException, model.simulate, options=opts) + with pytest.raises(FMUException): + model.simulate(options=opts) model = Dummy_FMUModelCS2([], os.path.join(file_path, "files", "FMUs", "XML", "CS2.0", "bouncingBall.fmu"), _connect_dll=False) opts = model.simulate_options() opts["initialize"] = False - nose.tools.assert_raises(FMUException, model.simulate, options=opts) + with pytest.raises(FMUException): + model.simulate(options=opts) - @testattr(stddist = True) - def test_simulation_with_syncronization_exception_ME(self): + def test_simulation_with_synchronization_exception_ME(self): """ Verifies the allowed values for the option to synchronize simulations (ME) """ @@ -1506,16 +1431,17 @@ def test_simulation_with_syncronization_exception_ME(self): opts = model.simulate_options() opts["synchronize_simulation"] = "Hej" - nose.tools.assert_raises(InvalidOptionException, model.simulate, options=opts) + with pytest.raises(InvalidOptionException): + model.simulate(options=opts) model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "bouncingBall.fmu"), _connect_dll=False) opts = model.simulate_options() opts["synchronize_simulation"] = -1.0 - nose.tools.assert_raises(InvalidOptionException, model.simulate, options=opts) + with pytest.raises(InvalidOptionException): + model.simulate(options=opts) - @testattr(stddist = True) - def test_simulation_with_syncronization_exception_CS(self): + def test_simulation_with_synchronization_exception_CS(self): """ Verifies the allowed values for the option to synchronize simulations (CS) """ @@ -1523,16 +1449,17 @@ def test_simulation_with_syncronization_exception_CS(self): opts = model.simulate_options() opts["synchronize_simulation"] = "Hej" - nose.tools.assert_raises(InvalidOptionException, model.simulate, options=opts) + with pytest.raises(InvalidOptionException): + model.simulate(options=opts) model = Dummy_FMUModelCS2([], os.path.join(file_path, "files", "FMUs", "XML", "CS2.0", "bouncingBall.fmu"), _connect_dll=False) opts = model.simulate_options() opts["synchronize_simulation"] = -1.0 - nose.tools.assert_raises(InvalidOptionException, model.simulate, options=opts) + with pytest.raises(InvalidOptionException): + model.simulate(options=opts) - @testattr(stddist = True) - def test_simulation_with_syncronization_ME(self): + def test_simulation_with_synchronization_ME(self): """ Verifies that the option synchronize simulation works as intended in the most basic test for ME FMUs. """ @@ -1550,11 +1477,10 @@ def test_simulation_with_syncronization_ME(self): res = model.simulate(final_time=0.1, options=opts) tsyn = res.detailed_timings["computing_solution"] - assert tsyn > t, "Syncronization does not work: %d, %d"%(t, tsyn) + assert tsyn > t, "synchronization does not work: %d, %d"%(t, tsyn) - @testattr(stddist = True) - def test_simulation_with_syncronization_CS(self): + def test_simulation_with_synchronization_CS(self): """ Verifies that the option synchronize simulation works as intended in the most basic test for CS FMUs. """ @@ -1572,9 +1498,8 @@ def test_simulation_with_syncronization_CS(self): res = model.simulate(final_time=0.1, options=opts) tsyn = res.detailed_timings["computing_solution"] - assert tsyn > t, "Syncronization does not work: %d, %d"%(t, tsyn) + assert tsyn > t, "synchronization does not work: %d, %d"%(t, tsyn) - @testattr(stddist = True) def test_caching(self): negated_alias = FMUModelME2(os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "NegatedAlias.fmu"), _connect_dll=False) @@ -1602,7 +1527,6 @@ def test_caching(self): vars_6 = negated_alias.get_model_variables() assert id(vars_1) != id(vars_6) - @testattr(stddist = True) def test_get_scalar_variable(self): negated_alias = FMUModelME2(os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "NegatedAlias.fmu"), _connect_dll=False) @@ -1615,38 +1539,33 @@ def test_get_scalar_variable(self): assert sc_x.causality == fmi.FMI2_LOCAL, sc_x.causality assert sc_x.initial == fmi.FMI2_INITIAL_APPROX, sc_x.initial - nose.tools.assert_raises(FMUException, negated_alias.get_scalar_variable, "not_existing") + with pytest.raises(FMUException): + negated_alias.get_scalar_variable("not_existing") - @testattr(stddist = True) def test_get_variable_description(self): model = FMUModelME2(FMU_PATHS.ME2.coupled_clutches, _connect_dll=False) assert model.get_variable_description("J1.phi") == "Absolute rotation angle of component" class Test_load_fmu_only_XML: - - @testattr(stddist = True) def test_loading_xml_me1(self): model = FMUModelME1(FMU_PATHS.ME1.coupled_clutches, _connect_dll=False) assert model.get_name() == "CoupledClutches", model.get_name() - @testattr(stddist = True) def test_loading_xml_cs1(self): model = FMUModelCS1(os.path.join(file_path, "files", "FMUs", "XML", "CS1.0", "CoupledClutches.fmu"), _connect_dll=False) assert model.get_name() == "CoupledClutches", model.get_name() - @testattr(stddist = True) def test_loading_xml_me2(self): model = FMUModelME2(FMU_PATHS.ME2.coupled_clutches, _connect_dll=False) assert model.get_name() == "CoupledClutches", model.get_name() - @testattr(stddist = True) def test_loading_xml_cs2(self): model = FMUModelCS2(os.path.join(file_path, "files", "FMUs", "XML", "CS2.0", "CoupledClutches.fmu"), _connect_dll=False) diff --git a/tests/test_fmi_coupled.py b/tests/test_fmi_coupled.py index b1b622a8..08899f8a 100644 --- a/tests/test_fmi_coupled.py +++ b/tests/test_fmi_coupled.py @@ -15,10 +15,9 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import nose +import pytest import os -from pyfmi import testattr from pyfmi.fmi import FMUModelME2 from pyfmi.fmi_coupled import CoupledFMUModelME2 import pyfmi.fmi as fmi @@ -36,7 +35,6 @@ if assimulo_installed: class Test_CoupledFMUModelME2_Simulation: - @testattr(stddist = True) def test_linear_example(self): model_sub_1 = Dummy_FMUModelME2([], os.path.join(me2_xml_path, "LinearStability.SubSystem1.fmu"), _connect_dll=False) model_sub_2 = Dummy_FMUModelME2([], os.path.join(me2_xml_path, "LinearStability.SubSystem2.fmu"), _connect_dll=False) @@ -76,20 +74,18 @@ def sub2(*args, **kwargs): res = coupled.simulate(options=opts) - nose.tools.assert_almost_equal(res.final("First.x1"),0.08597302307099872) - nose.tools.assert_almost_equal(res.final("Second.x2"),0.0083923348082567) - nose.tools.assert_almost_equal(res.initial("First.x1"),1.0) - nose.tools.assert_almost_equal(res.initial("Second.x2"),1.0) + assert res.final("First.x1") == pytest.approx(0.08597302307099872) + assert res.final("Second.x2") == pytest.approx(0.0083923348082567) + assert res.initial("First.x1") == pytest.approx(1.0) + assert res.initial("Second.x2") == pytest.approx(1.0) - nose.tools.assert_almost_equal(res.final("First.u1"),-0.25909975860402856) - nose.tools.assert_almost_equal(res.final("Second.u2"),-0.0011806893910324295) - nose.tools.assert_almost_equal(res.initial("First.u1"),-17.736842105263158) - nose.tools.assert_almost_equal(res.initial("Second.u2"),-14.73684210526316) + assert res.final("First.u1") == pytest.approx(-0.25909975860402856) + assert res.final("Second.u2") == pytest.approx(-0.0011806893910324295) + assert res.initial("First.u1") == pytest.approx(-17.736842105263158) + assert res.initial("Second.u2") == pytest.approx(-14.73684210526316) class Test_CoupledFMUModelME2: - - @testattr(stddist = True) def test_reversed_connections(self): model_sub_1 = FMUModelME2(os.path.join(me2_xml_path, "LinearStability.SubSystem1.fmu"), _connect_dll=False) model_sub_2 = FMUModelME2(os.path.join(me2_xml_path, "LinearStability.SubSystem2.fmu"), _connect_dll=False) @@ -99,16 +95,16 @@ def test_reversed_connections(self): connections = [(model_sub_2,"y1",model_sub_1,"u2"), (model_sub_1,"y2",model_sub_2,"u1")] - nose.tools.assert_raises(fmi.FMUException, CoupledFMUModelME2, models, connections) + with pytest.raises(fmi.FMUException): + CoupledFMUModelME2(models, connections) connections = [(model_sub_2,"u2",model_sub_1,"y1"), (model_sub_1,"u1",model_sub_2,"y2")] - nose.tools.assert_raises(fmi.FMUException, CoupledFMUModelME2, models, connections) + with pytest.raises(fmi.FMUException): + CoupledFMUModelME2(models, connections) - @testattr(stddist = True) def test_inputs_list(self): - model_sub_1 = FMUModelME2(os.path.join(me2_xml_path, "LinearStability.SubSystem1.fmu"), _connect_dll=False) model_sub_2 = FMUModelME2(os.path.join(me2_xml_path, "LinearStability.SubSystem2.fmu"), _connect_dll=False) model_full = FMUModelME2(os.path.join(me2_xml_path, "LinearStability.FullSystem.fmu"), _connect_dll=False) @@ -128,7 +124,6 @@ def test_inputs_list(self): assert "First.u1" in vars assert "Second.u2" in vars - @testattr(stddist = True) def test_alias(self): model_cc_1 = FMUModelME2(os.path.join(me2_xml_path, "CoupledClutches.fmu"), _connect_dll=False) model_cc_2 = FMUModelME2(os.path.join(me2_xml_path, "CoupledClutches.fmu"), _connect_dll=False) @@ -142,7 +137,6 @@ def test_alias(self): assert "First.J4.phi" in aliases.keys() assert coupled.get_variable_alias_base("First.J4.phi") == "First.J4.flange_a.phi" - @testattr(stddist = True) def test_loading(self): model_cc_1 = FMUModelME2(os.path.join(me2_xml_path, "CoupledClutches.fmu"), _connect_dll=False) model_cc_2 = FMUModelME2(os.path.join(me2_xml_path, "CoupledClutches.fmu"), _connect_dll=False) @@ -150,24 +144,28 @@ def test_loading(self): models = [model_cc_1, model_cc_2] connections = [] - nose.tools.assert_raises(fmi.FMUException, CoupledFMUModelME2, models, connections) + with pytest.raises(fmi.FMUException): + CoupledFMUModelME2(models, connections) models = [("First", model_cc_1), model_cc_2] - nose.tools.assert_raises(fmi.FMUException, CoupledFMUModelME2, models, connections) + with pytest.raises(fmi.FMUException): + CoupledFMUModelME2(models, connections) models = [("First", model_cc_1), ("First", model_cc_2)] - nose.tools.assert_raises(fmi.FMUException, CoupledFMUModelME2, models, connections) + with pytest.raises(fmi.FMUException): + CoupledFMUModelME2(models, connections) models = [("First", model_cc_1), ("Second", model_cc_2)] coupled = CoupledFMUModelME2(models, connections) connections = [("k")] - nose.tools.assert_raises(fmi.FMUException, CoupledFMUModelME2, models, connections) + with pytest.raises(fmi.FMUException): + CoupledFMUModelME2(models, connections) connections = [(model_cc_1, "J1.phi", model_cc_2, "J2.phi")] - nose.tools.assert_raises(fmi.FMUException, CoupledFMUModelME2, models, connections) + with pytest.raises(fmi.FMUException): + CoupledFMUModelME2(models, connections) - @testattr(stddist = True) def test_get_variable_valueref(self): model_cc_1 = FMUModelME2(os.path.join(me2_xml_path, "CoupledClutches.fmu"), _connect_dll=False) model_cc_2 = FMUModelME2(os.path.join(me2_xml_path, "CoupledClutches.fmu"), _connect_dll=False) @@ -177,7 +175,8 @@ def test_get_variable_valueref(self): coupled = CoupledFMUModelME2(models, connections) - nose.tools.assert_raises(fmi.FMUException, coupled.get_variable_valueref, "J1.w") + with pytest.raises(fmi.FMUException): + coupled.get_variable_valueref("J1.w") vr_1 = coupled.get_variable_valueref("First.J1.w") vr_2 = coupled.get_variable_valueref("Second.J1.w") @@ -190,7 +189,6 @@ def test_get_variable_valueref(self): assert var_name_1 == "First.J1.w" assert var_name_2 == "Second.J1.w" - @testattr(stddist = True) def test_ode_sizes(self): model_cc_1 = FMUModelME2(os.path.join(me2_xml_path, "CoupledClutches.fmu"), _connect_dll=False) model_cc_2 = FMUModelME2(os.path.join(me2_xml_path, "CoupledClutches.fmu"), _connect_dll=False) @@ -205,7 +203,6 @@ def test_ode_sizes(self): assert nbr_states == 16 assert nbr_event_ind == 66 - @testattr(stddist = True) def test_variable_variability(self): model_cc_1 = FMUModelME2(os.path.join(me2_xml_path, "CoupledClutches.fmu"), _connect_dll=False) model_cc_2 = FMUModelME2(os.path.join(me2_xml_path, "CoupledClutches.fmu"), _connect_dll=False) @@ -215,13 +212,13 @@ def test_variable_variability(self): coupled = CoupledFMUModelME2(models, connections) - nose.tools.assert_raises(fmi.FMUException, coupled.get_variable_variability, "J1.w") + with pytest.raises(fmi.FMUException): + coupled.get_variable_variability("J1.w") variability = coupled.get_variable_variability("First.J1.w") assert variability == model_cc_1.get_variable_variability("J1.w") - @testattr(stddist = True) def test_variable_causality(self): model_cc_1 = FMUModelME2(os.path.join(me2_xml_path, "CoupledClutches.fmu"), _connect_dll=False) model_cc_2 = FMUModelME2(os.path.join(me2_xml_path, "CoupledClutches.fmu"), _connect_dll=False) @@ -231,13 +228,13 @@ def test_variable_causality(self): coupled = CoupledFMUModelME2(models, connections) - nose.tools.assert_raises(fmi.FMUException, coupled.get_variable_causality, "J1.w") + with pytest.raises(fmi.FMUException): + coupled.get_variable_causality("J1.w") causality = coupled.get_variable_causality("First.J1.w") assert causality == model_cc_1.get_variable_causality("J1.w") - @testattr(stddist = True) def test_derivatives_list(self): model_cc_1 = FMUModelME2(os.path.join(me2_xml_path, "CoupledClutches.fmu"), _connect_dll=False) model_cc_2 = FMUModelME2(os.path.join(me2_xml_path, "CoupledClutches.fmu"), _connect_dll=False) @@ -255,7 +252,6 @@ def test_derivatives_list(self): alias_vars = coupled.get_variable_alias(var).keys() assert state in alias_vars - @testattr(stddist = True) def test_states_list(self): model_cc_1 = FMUModelME2(os.path.join(me2_xml_path, "CoupledClutches.fmu"), _connect_dll=False) model_cc_2 = FMUModelME2(os.path.join(me2_xml_path, "CoupledClutches.fmu"), _connect_dll=False) @@ -273,7 +269,6 @@ def test_states_list(self): alias_vars = coupled.get_variable_alias(var).keys() assert state in alias_vars - @testattr(stddist = True) def test_model_variables(self): model_cc_1 = FMUModelME2(os.path.join(me2_xml_path, "CoupledClutches.fmu"), _connect_dll=False) model_cc_2 = FMUModelME2(os.path.join(me2_xml_path, "CoupledClutches.fmu"), _connect_dll=False) diff --git a/tests/test_fmi_estimate.py b/tests/test_fmi_estimate.py index 0f438c09..a243b925 100644 --- a/tests/test_fmi_estimate.py +++ b/tests/test_fmi_estimate.py @@ -18,7 +18,6 @@ import os import numpy as np -from pyfmi import testattr from pyfmi.tests.test_util import Dummy_FMUModelME2 from scipy.io.matlab.mio import loadmat @@ -32,8 +31,6 @@ if assimulo_installed: class Test_FMUModelME2_Estimate: - - @testattr(stddist = True) def test_quadtank_estimate(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "QuadTankPack_Sim_QuadTank.fmu"), _connect_dll=False) diff --git a/tests/test_fmi_extended.py b/tests/test_fmi_extended.py index b0655012..f0045d89 100644 --- a/tests/test_fmi_extended.py +++ b/tests/test_fmi_extended.py @@ -18,7 +18,6 @@ import os import numpy as np -from pyfmi import testattr from pyfmi.fmi_extended import FMUModelME1Extended file_path = os.path.dirname(os.path.abspath(__file__)) @@ -27,14 +26,12 @@ class Test_FMUModelME1Extended: - @testattr(stddist = True) def test_log_file_name(self): model = FMUModelME1Extended(os.path.join(me1_xml_path, "bouncingBall.fmu"), _connect_dll=False) assert os.path.exists("bouncingBall_log.txt") model = FMUModelME1Extended(os.path.join(me1_xml_path, "bouncingBall.fmu"), log_file_name="Test_log.txt", _connect_dll=False) assert os.path.exists("Test_log.txt") - @testattr(stddist = True) def test_default_experiment(self): model = FMUModelME1Extended(os.path.join(me1_xml_path, "CoupledClutches.fmu"), _connect_dll=False) diff --git a/tests/test_fmi_master.py b/tests/test_fmi_master.py index c8f04dc2..a0c3f9ef 100644 --- a/tests/test_fmi_master.py +++ b/tests/test_fmi_master.py @@ -15,11 +15,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import nose +import pytest import os import numpy as np -from pyfmi import testattr, Master +from pyfmi import Master from pyfmi.fmi import FMUException, FMUModelCS2, FMUModelME2 from pyfmi.tests.test_util import Dummy_FMUModelCS2 from pyfmi.common.algorithm_drivers import UnrecognizedOptionError @@ -33,8 +33,6 @@ warnings.filterwarnings("ignore") class Test_Master: - - @testattr(stddist = True) def test_loading_models(self): model_sub1 = FMUModelCS2(os.path.join(cs2_xml_path, "LinearStability.SubSystem1.fmu"), _connect_dll=False) model_sub2 = FMUModelCS2(os.path.join(cs2_xml_path, "LinearStability.SubSystem2.fmu"), _connect_dll=False) @@ -46,7 +44,6 @@ def test_loading_models(self): #Assert that loading is successful sim = Master(models, connections) - @testattr(stddist = True) def test_loading_wrong_model(self): model_sub1 = FMUModelCS2(os.path.join(cs2_xml_path, "LinearStability.SubSystem1.fmu"), _connect_dll=False) model_sub2 = FMUModelME2(os.path.join(me2_xml_path, "LinearStability.SubSystem2.fmu"), _connect_dll=False) @@ -55,9 +52,9 @@ def test_loading_wrong_model(self): connections = [(model_sub1,"y1",model_sub2,"u2"), (model_sub2,"y2",model_sub1,"u1")] - nose.tools.assert_raises(FMUException, Master, models, connections) + with pytest.raises(FMUException): + Master(models, connections) - @testattr(stddist = True) def test_connection_variables(self): model_sub1 = FMUModelCS2(os.path.join(cs2_xml_path, "LinearStability.SubSystem1.fmu"), _connect_dll=False) model_sub2 = FMUModelCS2(os.path.join(cs2_xml_path, "LinearStability.SubSystem2.fmu"), _connect_dll=False) @@ -68,15 +65,16 @@ def test_connection_variables(self): connections = [(model_sub1,"y1",model_sub2,"x2"), (model_sub2,"y2",model_sub1,"u1")] - nose.tools.assert_raises(FMUException, Master, models, connections) + with pytest.raises(FMUException): + Master(models, connections) #Test wrong input / output order connections = [(model_sub2,"u2", model_sub1,"y1"), (model_sub2,"y2",model_sub1,"u1")] - nose.tools.assert_raises(FMUException, Master, models, connections) + with pytest.raises(FMUException): + Master(models, connections) - @testattr(stddist = True) def test_basic_algebraic_loop(self): model_sub1 = FMUModelCS2(os.path.join(cs2_xml_path, "LinearStability.SubSystem1.fmu"), _connect_dll=False) model_sub2 = FMUModelCS2(os.path.join(cs2_xml_path, "LinearStability.SubSystem2.fmu"), _connect_dll=False) @@ -145,8 +143,8 @@ def _sim_basic_simulation(self, models, connections, opts_update): opts.update(opts_update) res = master.simulate(options=opts) - nose.tools.assert_almost_equal(res[models[0]].final("x1"), 0.0859764038708439, 3) - nose.tools.assert_almost_equal(res[models[1]].final("x2"), 0.008392664839635064, 4) + assert res[models[0]].final("x1") == pytest.approx(0.0859764038708439, abs = 1e-3) + assert res[models[1]].final("x2") == pytest.approx(0.008392664839635064, abs = 1e-4) return res @@ -155,17 +153,14 @@ def _basic_simulation(self, opts_update): self._sim_basic_simulation(models, connections, opts_update) - @testattr(stddist = True) def test_basic_simulation_txt_file(self): opts = {"result_handling":"file"} self._basic_simulation(opts) - @testattr(stddist = True) def test_basic_simulation_mat_file(self): opts = {"result_handling":"binary"} self._basic_simulation(opts) - @testattr(stddist = True) def test_basic_simulation_mat_file_naming(self): opts = {"result_handling":"binary", "result_file_name": "Should fail..."} @@ -181,7 +176,6 @@ def test_basic_simulation_mat_file_naming(self): except UnrecognizedOptionError: pass - @testattr(stddist = True) def test_basic_simulation_mat_file_naming_exists(self): models, connections = self._load_basic_simulation() @@ -192,7 +186,6 @@ def test_basic_simulation_mat_file_naming_exists(self): assert os.path.isfile("Test1.mat"), "Test1.mat does not exists" assert os.path.isfile("Test2.mat"), "Test2.mat does not exists" - @testattr(stddist = True) def test_basic_simulation_txt_file_naming_exists(self): models, connections = self._load_basic_simulation() @@ -203,12 +196,10 @@ def test_basic_simulation_txt_file_naming_exists(self): assert os.path.isfile("Test1.txt"), "Test1.txt does not exists" assert os.path.isfile("Test2.txt"), "Test2.txt does not exists" - @testattr(stddist = True) def test_basic_simulation_with_block_initialization(self): opts = {"block_initialization": True} self._basic_simulation(opts) - @testattr(stddist = True) def test_integer_connections(self): model_sub1 = Dummy_FMUModelCS2([], os.path.join(cs2_xml_path, "IntegerStep.fmu"), _connect_dll=False) model_sub2 = Dummy_FMUModelCS2([], os.path.join(cs2_xml_path, "GainTestInteger.fmu"), _connect_dll=False) @@ -241,7 +232,6 @@ def do_step2(current_t, step_size, new_step=True): assert res[model_sub2]["u"][0] == 1 assert res[model_sub2]["u"][-1] == 3 - @testattr(stddist = True) def test_integer_to_real_connections(self): model_sub1 = Dummy_FMUModelCS2([], os.path.join(cs2_xml_path, "IntegerStep.fmu"), _connect_dll=False) model_sub2 = Dummy_FMUModelCS2([], os.path.join(cs2_xml_path, "GainTestReal.fmu"), _connect_dll=False) @@ -274,7 +264,6 @@ def do_step2(current_t, step_size, new_step=True): assert res[model_sub2]["u"][0] == 1.0 assert res[model_sub2]["u"][-1] == 3.0 - @testattr(stddist = True) def test_unstable_simulation(self): model_sub1 = Dummy_FMUModelCS2([], os.path.join(cs2_xml_path, "LinearCoSimulation_LinearSubSystem1.fmu"), _connect_dll=False) model_sub2 = Dummy_FMUModelCS2([], os.path.join(cs2_xml_path, "LinearCoSimulation_LinearSubSystem2.fmu"), _connect_dll=False) diff --git a/tests/test_fmi_util.py b/tests/test_fmi_util.py index 5c03a930..ac717872 100644 --- a/tests/test_fmi_util.py +++ b/tests/test_fmi_util.py @@ -22,12 +22,9 @@ import numpy as np from collections import OrderedDict -from pyfmi import testattr import pyfmi.fmi_util as fmi_util class Test_FMIUtil: - - @testattr(stddist = True) def test_cpr_seed(self): structure = OrderedDict([('der(inertia3.phi)', ['inertia3.w']), ('der(inertia3.w)', ['damper.phi_rel', 'inertia3.phi']), @@ -46,7 +43,6 @@ def test_cpr_seed(self): assert np.array(groups[1][4] == [3,4]).all() assert np.array(groups[2][4] == [5,6]).all() - @testattr(stddist = True) def test_cpr_seed_interested_columns(self): structure = OrderedDict([('der(inertia3.phi)', ['inertia3.w']), ('der(inertia3.w)', ['damper.phi_rel', 'inertia3.phi']), diff --git a/tests/test_io.py b/tests/test_io.py index 7232740c..47d5e262 100644 --- a/tests/test_io.py +++ b/tests/test_io.py @@ -15,21 +15,20 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . -import nose +import pytest import os import numpy as np import time from io import StringIO, BytesIO from collections import OrderedDict -from pyfmi import testattr from pyfmi.fmi import FMUException, FMUModelME2 from pyfmi.common.io import (ResultHandler, ResultDymolaTextual, ResultDymolaBinary, JIOError, ResultHandlerCSV, ResultCSVTextual, ResultHandlerBinaryFile, ResultHandlerFile) from pyfmi.common.diagnostics import DIAGNOSTICS_PREFIX import pyfmi.fmi as fmi -from pyfmi.tests.test_util import Dummy_FMUModelME1, Dummy_FMUModelME2, Dummy_FMUModelCS2 +from pyfmi.tests.test_util import Dummy_FMUModelME1, Dummy_FMUModelCS1, Dummy_FMUModelME2, Dummy_FMUModelCS2 file_path = os.path.dirname(os.path.abspath(__file__)) @@ -48,14 +47,13 @@ def _run_negated_alias(model, result_type, result_file_name=""): # test that res['y'] returns a vector of the same length as the time # vector - nose.tools.assert_equal(len(res['y']),len(res['time']), - "Wrong size of result vector.") + assert len(res['y']) ==len(res['time']), "Wrong size of result vector." x = res["x"] y = res["y"] for i in range(len(x)): - nose.tools.assert_equal(x[i], -y[i]) + assert x[i] == -y[i] if assimulo_installed: class TestResultFileText_Simulation: @@ -93,18 +91,15 @@ def f(*args, **kwargs): assert len(x) > 2 for i in range(len(x)): - nose.tools.assert_equal(x[i], -y[i]) + assert x[i] == -y[i] - @testattr(stddist = True) def test_correct_file_after_simulation_failure(self): self._correct_syntax_after_simulation_failure("NegatedAlias_result.txt") - @testattr(stddist = True) def test_correct_stream_after_simulation_failure(self): stream = StringIO("") self._correct_syntax_after_simulation_failure(stream) - @testattr(stddist = True) def test_read_all_variables_using_model_variables(self): simple_alias = Dummy_FMUModelME2([("x", "y")], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "NegatedAlias.fmu"), _connect_dll=False) @@ -117,7 +112,6 @@ def test_read_all_variables_using_model_variables(self): for var in simple_alias.get_model_variables(): res[var] - @testattr(stddist = True) def test_read_alias_derivative(self): simple_alias = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "Alias.fmu"), _connect_dll=False) @@ -130,9 +124,8 @@ def test_read_alias_derivative(self): dery = res["der(y)"] for i in range(len(derx)): - nose.tools.assert_equal(derx[i], dery[i]) + assert derx[i] == dery[i] - @testattr(stddist = True) def test_no_variables(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "ParameterAlias.fmu"), _connect_dll=False) @@ -143,9 +136,8 @@ def test_no_variables(self): res = model.simulate(options=opts) - nose.tools.assert_almost_equal(1.0, res["time"][-1]) + assert 1.0 == pytest.approx(res["time"][-1]) - @testattr(stddist = True) def test_enumeration_file(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "Friction2.fmu"), _connect_dll=False) @@ -160,8 +152,6 @@ def test_enumeration_file(self): res["mode"] #Check that the enumeration variable is in the dict, otherwise exception class TestResultFileText: - - def _get_description(self, result_file_name): model = Dummy_FMUModelME1([], os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "CoupledClutches.fmu"), _connect_dll=False) model.initialize() @@ -179,16 +169,13 @@ def _get_description(self, result_file_name): assert res.description[res.get_variable_index("J1.phi")] == "Absolute rotation angle of component" - @testattr(stddist = True) def test_get_description_file(self): self._get_description('CoupledClutches_result.txt') - @testattr(stddist = True) def test_get_description_stream(self): stream = StringIO() self._get_description(stream) - @testattr(stddist = True) def test_description_not_stored(self): model = Dummy_FMUModelME1([], os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "CoupledClutches.fmu"), _connect_dll=False) model.initialize() @@ -225,11 +212,9 @@ def _get_description_unicode(self, result_file_name): assert desc == u"Test symbols '' ‘’" - @testattr(stddist = True) def _get_description_unicode_file(self): self._get_description_unicode('Description_result.txt') - @testattr(stddist = True) def _get_description_unicode_stream(self): stream = StringIO() self._get_description_unicode(stream) @@ -255,14 +240,12 @@ def _work_flow_me1(self, result_file_name): derh = res.get_variable_data('der(h)') g = res.get_variable_data('g') - nose.tools.assert_almost_equal(h.x, 1.000000, 5) - nose.tools.assert_almost_equal(derh.x, 0.000000, 5) + assert h.x == pytest.approx(1.000000, abs = 1e-5) + assert derh.x == pytest.approx(0.000000, abs = 1e-5) - @testattr(stddist = True) def test_work_flow_me1_file(self): self._work_flow_me1('bouncingBall_result.txt') - @testattr(stddist = True) def test_work_flow_me1_stream(self): stream = StringIO() self._work_flow_me1(stream) @@ -289,19 +272,16 @@ def _work_flow_me2(self, result_file_name): derh = res.get_variable_data('der(h)') g = res.get_variable_data('g') - nose.tools.assert_almost_equal(h.x, 1.000000, 5) - nose.tools.assert_almost_equal(derh.x, 0.000000, 5) + assert h.x == pytest.approx(1.000000, abs = 1e-5) + assert derh.x == pytest.approx(0.000000, abs = 1e-5) - @testattr(stddist = True) def test_work_flow_me2_file(self): self._work_flow_me2('bouncingBall_result.txt') - @testattr(stddist = True) def test_work_flow_me2_stream(self): stream = StringIO() self._work_flow_me2(stream) - @testattr(stddist = True) def test_work_flow_me2_stream2(self): """ Verify exception when using ResultHandlerFile with a stream that doesnt support 'seek'. """ class A: @@ -309,10 +289,9 @@ def write(self): pass stream = A() msg = "Failed to write the result file. Option 'result_file_name' needs to be a filename or a class that supports 'write' and 'seek'." - with nose.tools.assert_raises_regex(FMUException, msg): + with pytest.raises(FMUException, match = msg): self._work_flow_me2(stream) - @testattr(stddist = True) def test_work_flow_me2_stream3(self): """ Verify exception when using ResultHandlerFile with a stream that doesnt support 'write'. """ class A: @@ -320,10 +299,9 @@ def seek(self): pass stream = A() msg = "Failed to write the result file. Option 'result_file_name' needs to be a filename or a class that supports 'write' and 'seek'." - with nose.tools.assert_raises_regex(FMUException, msg): + with pytest.raises(FMUException, match = msg): self._work_flow_me2(stream) - @testattr(stddist = True) def test_constructor_invalid_stream1(self): """ Verify exception is raised for ResultDymolaTextual if fname argument is a stream not supporting 'readline'. """ class A: @@ -331,10 +309,9 @@ def seek(self): pass stream = A() msg = "Given stream needs to support 'readline' and 'seek' in order to retrieve the results." - with nose.tools.assert_raises_regex(JIOError, msg): + with pytest.raises(JIOError, match = msg): res = ResultDymolaTextual(stream) - @testattr(stddist = True) def test_constructor_invalid_stream2(self): """ Verify exception is raised for ResultDymolaTextual if fname argument is a stream not supporting 'seek'. """ class A: @@ -342,22 +319,19 @@ def readline(self): pass stream = A() msg = "Given stream needs to support 'readline' and 'seek' in order to retrieve the results." - with nose.tools.assert_raises_regex(JIOError, msg): + with pytest.raises(JIOError, match = msg): res = ResultDymolaTextual(stream) if assimulo_installed: class TestResultMemory_Simulation: - @testattr(stddist = True) def test_memory_options_me1(self): simple_alias = Dummy_FMUModelME1([40], os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "NegatedAlias.fmu"), _connect_dll=False) _run_negated_alias(simple_alias, "memory") - @testattr(stddist = True) def test_memory_options_me2(self): simple_alias = Dummy_FMUModelME2([("x", "y")], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "NegatedAlias.fmu"), _connect_dll=False) _run_negated_alias(simple_alias, "memory") - @testattr(stddist = True) def test_only_parameters(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "ParameterAlias.fmu"), _connect_dll=False) @@ -367,11 +341,10 @@ def test_only_parameters(self): res = model.simulate(options=opts) - nose.tools.assert_almost_equal(3.0, res["p2"][0]) + assert 3.0 == pytest.approx(res["p2"][0]) assert not isinstance(res.initial("p2"), np.ndarray) assert not isinstance(res.final("p2"), np.ndarray) - @testattr(stddist = True) def test_no_variables(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "ParameterAlias.fmu"), _connect_dll=False) @@ -381,11 +354,9 @@ def test_no_variables(self): res = model.simulate(options=opts) - nose.tools.assert_almost_equal(1.0, res["time"][-1]) + assert 1.0 == pytest.approx(res["time"][-1]) - @testattr(stddist = True) def test_enumeration_memory(self): - model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "Friction2.fmu"), _connect_dll=False) data_type = model.get_variable_data_type("mode") @@ -402,7 +373,6 @@ class TestResultMemory: if assimulo_installed: class TestResultFileBinary_Simulation: - def _correct_file_after_simulation_failure(self, result_file_name): simple_alias = Dummy_FMUModelME2([("x", "y")], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "NegatedAlias.fmu"), _connect_dll=False) @@ -436,14 +406,12 @@ def f(*args, **kwargs): assert len(x) > 2 for i in range(len(x)): - nose.tools.assert_equal(x[i], -y[i]) + assert x[i] == -y[i] - @testattr(stddist = True) def test_work_flow_me2_file(self): self._correct_file_after_simulation_failure("NegatedAlias_result.mat") - @testattr(stddist = True) def test_work_flow_me2_stream(self): stream = BytesIO() self._correct_file_after_simulation_failure(stream) @@ -459,13 +427,11 @@ def _only_parameters(self, result_file_name): res = model.simulate(options=opts) - nose.tools.assert_almost_equal(3.0, res["p2"][0]) + assert 3.0 == pytest.approx(res["p2"][0]) - @testattr(stddist = True) def test_only_parameters_file(self): self._only_parameters("ParameterAlias_result.mat") - @testattr(stddist = True) def test_only_parameters_stream(self): stream = BytesIO() self._only_parameters(stream) @@ -481,19 +447,16 @@ def _no_variables(self, result_file_name): res = model.simulate(options=opts) - nose.tools.assert_almost_equal(1.0, res["time"][-1]) + assert 1.0 == pytest.approx(res["time"][-1]) - @testattr(stddist = True) def test_no_variables_file(self): self._no_variables("ParameterAlias_result.mat") - @testattr(stddist = True) def test_no_variables_stream(self): stream = BytesIO() self._no_variables(stream) - @testattr(stddist = True) def test_read_alias_derivative(self): simple_alias = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "Alias.fmu"), _connect_dll=False) @@ -506,11 +469,9 @@ def test_read_alias_derivative(self): dery = res["der(y)"] for i in range(len(derx)): - nose.tools.assert_equal(derx[i], dery[i]) + assert derx[i] == dery[i] - @testattr(stddist = True) def test_enumeration_binary(self): - model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "Friction2.fmu"), _connect_dll=False) data_type = model.get_variable_data_type("mode") @@ -523,7 +484,6 @@ def test_enumeration_binary(self): res = model.simulate(options=opts) res["mode"] #Check that the enumeration variable is in the dict, otherwise exception - @testattr(stddist = True) def test_integer_start_time(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "Alias.fmu"), _connect_dll=False) @@ -533,7 +493,6 @@ def test_integer_start_time(self): #Assert that there is no exception when reloading the file res = model.simulate(start_time=0, options=opts) - @testattr(stddist = True) def test_read_all_variables_using_model_variables(self): simple_alias = Dummy_FMUModelME2([("x", "y")], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "NegatedAlias.fmu"), _connect_dll=False) @@ -546,7 +505,6 @@ def test_read_all_variables_using_model_variables(self): for var in simple_alias.get_model_variables(): res[var] - @testattr(stddist = True) def test_variable_alias_custom_handler(self): simple_alias = Dummy_FMUModelME2([("x", "y")], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "NegatedAlias.fmu"), _connect_dll=False) @@ -558,39 +516,33 @@ def test_variable_alias_custom_handler(self): # test that res['y'] returns a vector of the same length as the time # vector - nose.tools.assert_equal(len(res['y']),len(res['time']), - "Wrong size of result vector.") + assert len(res['y']) ==len(res['time']), "Wrong size of result vector." x = res["x"] y = res["y"] for i in range(len(x)): - nose.tools.assert_equal(x[i], -y[i]) + assert x[i] == -y[i] - @testattr(stddist = True) def test_binary_options_me1(self): simple_alias = Dummy_FMUModelME1([40], os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "NegatedAlias.fmu"), _connect_dll=False) _run_negated_alias(simple_alias, "binary") - @testattr(stddist = True) def test_binary_options_me2(self): simple_alias = Dummy_FMUModelME2([("x", "y")], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "NegatedAlias.fmu"), _connect_dll=False) _run_negated_alias(simple_alias, "binary") - @testattr(stddist = True) def test_binary_options_me1_stream(self): simple_alias = Dummy_FMUModelME1([40], os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "NegatedAlias.fmu"), _connect_dll=False) stream = BytesIO() _run_negated_alias(simple_alias, "binary", stream) - @testattr(stddist = True) def test_binary_options_me2_stream(self): simple_alias = Dummy_FMUModelME2([("x", "y")], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "NegatedAlias.fmu"), _connect_dll=False) stream = BytesIO() _run_negated_alias(simple_alias, "binary", stream) class TestResultFileBinary: - def _get_description_unicode(self, result_file_name): model = Dummy_FMUModelME1([], os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "Description.fmu"), _connect_dll=False) model.initialize() @@ -612,16 +564,13 @@ def _get_description_unicode(self, result_file_name): assert desc == u"Test symbols '' ‘’" - @testattr(stddist = True) def test_get_description_unicode_file(self): self._get_description_unicode('Description_result.mat') - @testattr(stddist = True) def test_get_description_unicode_stream(self): stream = BytesIO() self._get_description_unicode(stream) - @testattr(stddist = True) def test_get_description(self): model = Dummy_FMUModelME1([], os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "CoupledClutches.fmu"), _connect_dll=False) model.initialize() @@ -637,7 +586,6 @@ def test_get_description(self): assert res.description[res.get_variable_index("J1.phi")] == "Absolute rotation angle of component" - @testattr(stddist = True) def test_modified_result_file_data_diagnostics(self): """Verify that computed diagnostics can be retrieved from an updated result file""" model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "CoupledClutches.fmu"), _connect_dll=False) @@ -689,7 +637,6 @@ def test_modified_result_file_data_diagnostics(self): assert len(res.get_variable_data("@Diagnostics.state_errors.clutch2.w_rel").x) == 4, res.get_variable_data("@Diagnostics.state_errors.clutch2.w_rel").x - @testattr(stddist = True) def test_modified_result_file_data_diagnostics_steps(self): """Verify that diagnostics can be retrieved from an updated result file""" model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "CoupledClutches.fmu"), _connect_dll=False) @@ -741,7 +688,6 @@ def test_modified_result_file_data_diagnostics_steps(self): assert len(res.get_variable_data("@Diagnostics.nbr_steps").x) == 4, res.get_variable_data("@Diagnostics.nbr_steps").x - @testattr(stddist = True) def test_modified_result_file_data_2(self): """Verify that continuous trajectories are updated when retrieved from a result file""" model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "CoupledClutches.fmu"), _connect_dll=False) @@ -764,7 +710,6 @@ def test_modified_result_file_data_2(self): assert len(res.get_variable_data("J1.phi").x) == 2, res.get_variable_data("J1.phi").x - @testattr(stddist = True) def test_modified_result_file_data_2_different(self): """Verify that (different) continuous trajectories are updated when retrieved from a result file""" model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "CoupledClutches.fmu"), _connect_dll=False) @@ -787,7 +732,6 @@ def test_modified_result_file_data_2_different(self): assert len(res.get_variable_data("J2.phi").x) == 2, res.get_variable_data("J2.phi").x - @testattr(stddist = True) def test_modified_result_file_data_1(self): """Verify that (different) constants/parameters can be retrieved from an updated result file""" model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "CoupledClutches.fmu"), _connect_dll=False) @@ -812,7 +756,6 @@ def test_modified_result_file_data_1(self): #Assert that no exception is raised res.get_variable_data("J2.J") - @testattr(stddist = True) def test_modified_result_file_data_1_delayed(self): """Verify that constants/parameters can be retrieved from an updated result file""" model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "CoupledClutches.fmu"), _connect_dll=False) @@ -833,7 +776,6 @@ def test_modified_result_file_data_1_delayed(self): #Assert that no exception is raised res.get_variable_data("J2.J") - @testattr(stddist = True) def test_modified_result_file_time(self): """Verify that 'time' can be retrieved from an updated result file""" model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "CoupledClutches.fmu"), _connect_dll=False) @@ -855,7 +797,6 @@ def test_modified_result_file_time(self): res.get_variable_data("time") - @testattr(stddist = True) def test_description_not_stored(self): model = Dummy_FMUModelME1([], os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "CoupledClutches.fmu"), _connect_dll=False) model.initialize() @@ -874,7 +815,6 @@ def test_description_not_stored(self): assert res.description[res.get_variable_index("J1.phi")] == "", "Description is not empty, " + res.description[res.get_variable_index("J1.phi")] - @testattr(stddist = True) def test_overwriting_results(self): model = Dummy_FMUModelME1([], os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "CoupledClutches.fmu"), _connect_dll=False) model.initialize() @@ -901,9 +841,9 @@ def test_overwriting_results(self): result_writer.integration_point() result_writer.simulation_end() - nose.tools.assert_raises(JIOError,res.get_variable_data, "J1.phi") + with pytest.raises(JIOError): + res.get_variable_data("J1.phi") - @testattr(stddist = True) def test_read_all_variables(self): res = ResultDymolaBinary(os.path.join(file_path, "files", "Results", "DoublePendulum.mat")) @@ -912,7 +852,6 @@ def test_read_all_variables(self): for var in res.name: res.get_variable_data(var) - @testattr(stddist = True) def test_data_matrix_delayed_loading(self): res = ResultDymolaBinary(os.path.join(file_path, "files", "Results", "DoublePendulum.mat"), delayed_trajectory_loading=True) @@ -923,7 +862,6 @@ def test_data_matrix_delayed_loading(self): assert nbr_continuous_variables == 68, "Number of variables is incorrect, should be 68" assert nbr_points == 502, "Number of points is incorrect, should be 502" - @testattr(stddist = True) def test_data_matrix_loading(self): res = ResultDymolaBinary(os.path.join(file_path, "files", "Results", "DoublePendulum.mat"), delayed_trajectory_loading=False) @@ -934,7 +872,6 @@ def test_data_matrix_loading(self): assert nbr_continuous_variables == 68, "Number of variables is incorrect, should be 68" assert nbr_points == 502, "Number of points is incorrect, should be 502" - @testattr(stddist = True) def test_read_all_variables_from_stream(self): with open(os.path.join(file_path, "files", "Results", "DoublePendulum.mat"), "rb") as f: @@ -945,7 +882,6 @@ def test_read_all_variables_from_stream(self): for var in res.name: res.get_variable_data(var) - @testattr(stddist = True) def test_compare_all_variables_from_stream(self): res_file = ResultDymolaBinary(os.path.join(file_path, "files", "Results", "DoublePendulum.mat")) @@ -961,7 +897,6 @@ def test_compare_all_variables_from_stream(self): np.testing.assert_array_equal(x_file.x, x_stream.x, err_msg="Mismatch in array values for var=%s"%var) - @testattr(stddist = True) def test_on_demand_loading_32_bits(self): res_demand = ResultDymolaBinary(os.path.join(file_path, "files", "Results", "DoublePendulum.mat")) res_all = ResultDymolaBinary(os.path.join(file_path, "files", "Results", "DoublePendulum.mat")) @@ -969,7 +904,6 @@ def test_on_demand_loading_32_bits(self): t_all = res_all.get_variable_data('time').x np.testing.assert_array_equal(t_demand, t_all, "On demand loaded result and all loaded does not contain equal result.") - @testattr(stddist = True) def test_work_flow_me1(self): model = Dummy_FMUModelME1([], os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "bouncingBall.fmu"), _connect_dll=False) model.initialize() @@ -988,10 +922,9 @@ def test_work_flow_me1(self): derh = res.get_variable_data('der(h)') g = res.get_variable_data('g') - nose.tools.assert_almost_equal(h.x, 1.000000, 5) - nose.tools.assert_almost_equal(derh.x, 0.000000, 5) + assert h.x == pytest.approx(1.000000, abs = 1e-5) + assert derh.x == pytest.approx(0.000000, abs = 1e-5) - @testattr(stddist = True) def test_many_variables_long_descriptions(self): """ Tests that large FMUs with lots of variables and huge length of descriptions gives @@ -1003,9 +936,9 @@ def test_many_variables_long_descriptions(self): res = ResultHandlerBinaryFile(model) res.set_options(model.simulate_options()) - nose.tools.assert_raises(FMUException,res.simulation_start) + with pytest.raises(FMUException): + res.simulation_start() - @testattr(stddist = True) def test_work_flow_me2(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "bouncingBall.fmu"), _connect_dll=False) model.setup_experiment() @@ -1025,8 +958,8 @@ def test_work_flow_me2(self): derh = res.get_variable_data('der(h)') g = res.get_variable_data('g') - nose.tools.assert_almost_equal(h.x[0], 1.000000, 5) - nose.tools.assert_almost_equal(derh.x[0], 0.000000, 5) + assert h.x[0] == pytest.approx(1.000000, abs = 1e-5) + assert derh.x[0] == pytest.approx(0.000000, abs = 1e-5) def _work_flow_me2_aborted(self, result_file_name): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "bouncingBall.fmu"), _connect_dll=False) @@ -1053,34 +986,30 @@ def _work_flow_me2_aborted(self, result_file_name): h = res.get_variable_data('h') derh = res.get_variable_data('der(h)') - nose.tools.assert_almost_equal(h.x[0], 1.000000, 5, msg="Incorrect initial value for 'h', should be 1.0") - nose.tools.assert_almost_equal(derh.x[0], 0.000000, 5, msg="Incorrect value for 'derh', should be 0.0") - nose.tools.assert_almost_equal(h.x[1], 1.000000, 5, msg="Incorrect value for 'h', should be 1.0") - nose.tools.assert_almost_equal(derh.x[1], 0.000000, 5, msg="Incorrect value for 'derh', should be 0.0") - nose.tools.assert_almost_equal(h.x[2], 1.000000, 5, msg="Incorrect value for 'h', should be 1.0") - nose.tools.assert_almost_equal(derh.x[2], 0.000000, 5, msg="Incorrect value for 'derh', should be 0.0") + assert h.x[0] == pytest.approx(1.000000, abs = 1e-5), "Incorrect initial value for 'h', should be 1.0" + assert derh.x[0] == pytest.approx(0.000000, abs = 1e-5), "Incorrect value for 'derh', should be 0.0" + assert h.x[1] == pytest.approx(1.000000, abs = 1e-5), "Incorrect value for 'h', should be 1.0" + assert derh.x[1] == pytest.approx(0.000000, abs = 1e-5), "Incorrect value for 'derh', should be 0.0" + assert h.x[2] == pytest.approx(1.000000, abs = 1e-5), "Incorrect value for 'h', should be 1.0" + assert derh.x[2] == pytest.approx(0.000000, abs = 1e-5), "Incorrect value for 'derh', should be 0.0" - @testattr(stddist = True) def test_work_flow_me2_aborted_file(self): self._work_flow_me2_aborted('bouncingBall_result.mat') - @testattr(stddist = True) def test_work_flow_me2_aborted_stream(self): """ Verify expected workflow for ME2 aborted simulation using byte stream. """ stream = BytesIO() self._work_flow_me2_aborted(stream) - @testattr(stddist = True) def test_work_flow_me2_aborted_stream2(self): """ Verify exception when using ResultHandlerBinaryFile with a stream that doesnt support anything. """ class A: pass stream = A() msg = "Failed to write the result file. Option 'result_file_name' needs to be a filename or a class that supports 'write', 'tell' and 'seek'." - with nose.tools.assert_raises_regex(FMUException, msg): + with pytest.raises(FMUException, match = msg): self._work_flow_me2_aborted(stream) - @testattr(stddist = True) def test_work_flow_me2_aborted_stream3(self): """ Verify exception when using ResultHandlerBinaryFile with a stream that doesnt support 'seek'. """ class A: @@ -1090,10 +1019,9 @@ def tell(self): pass stream = A() msg = "Failed to write the result file. Option 'result_file_name' needs to be a filename or a class that supports 'write', 'tell' and 'seek'." - with nose.tools.assert_raises_regex(FMUException, msg): + with pytest.raises(FMUException, match = msg): self._work_flow_me2_aborted(stream) - @testattr(stddist = True) def test_work_flow_me2_aborted_stream4(self): """ Verify exception when using ResultHandlerBinaryFile with a stream that doesnt support 'tell'. """ class A: @@ -1103,10 +1031,9 @@ def seek(self): pass stream = A() msg = "Failed to write the result file. Option 'result_file_name' needs to be a filename or a class that supports 'write', 'tell' and 'seek'." - with nose.tools.assert_raises_regex(FMUException, msg): + with pytest.raises(FMUException, match = msg): self._work_flow_me2_aborted(stream) - @testattr(stddist = True) def test_work_flow_me2_aborted_stream5(self): """ Verify exception when using ResultHandlerBinaryFile with a stream that doesnt support 'write'. """ class A: @@ -1116,10 +1043,9 @@ def tell(self): pass stream = A() msg = "Failed to write the result file. Option 'result_file_name' needs to be a filename or a class that supports 'write', 'tell' and 'seek'." - with nose.tools.assert_raises_regex(FMUException, msg): + with pytest.raises(FMUException, match = msg): self._work_flow_me2_aborted(stream) - @testattr(stddist = True) def test_filter_no_variables(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "bouncingBall.fmu"), _connect_dll=False) model.setup_experiment() @@ -1140,14 +1066,12 @@ def test_filter_no_variables(self): res = ResultDymolaBinary('bouncingBall_result.mat') t = res.get_variable_data('time') - nose.tools.assert_almost_equal(t.x[-1], 1.000000, 5) + assert t.x[-1] == pytest.approx(1.000000, abs = 1e-5) - @testattr(stddist = True) def test_binary_options_cs2(self): simple_alias = Dummy_FMUModelCS2([("x", "y")], os.path.join(file_path, "files", "FMUs", "XML", "CS2.0", "NegatedAlias.fmu"), _connect_dll=False) _run_negated_alias(simple_alias, "binary") - @testattr(stddist = True) def test_binary_options_cs2_stream(self): simple_alias = Dummy_FMUModelCS2([("x", "y")], os.path.join(file_path, "files", "FMUs", "XML", "CS2.0", "NegatedAlias.fmu"), _connect_dll=False) stream = BytesIO() @@ -1160,7 +1084,6 @@ def _get_bouncing_ball_dummy(self, fmu_type = 'me2'): elif fmu_type == 'me1': return Dummy_FMUModelME1([], os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "bouncingBall.fmu"), _connect_dll=False) - @testattr(stddist = True) def test_exception_simulation_start(self): """ Verify exception is raised if simulation_start is invoked without arguments. """ model = self._get_bouncing_ball_dummy() @@ -1173,7 +1096,7 @@ def test_exception_simulation_start(self): bouncingBall.set_options(opts) msg = "Unable to start simulation. The following keyword argument\(s\) are empty:" msg += " 'diagnostics\_params' and 'diagnostics\_vars'." - with nose.tools.assert_raises_regex(FMUException, msg): + with pytest.raises(FMUException, match = msg): bouncingBall.simulation_start() def _get_diagnostics_cancelled_sim(self, result_file_name): @@ -1244,23 +1167,20 @@ def _get_diagnostics_cancelled_sim(self, result_file_name): ev_ind = res.get_variable_data(DIAGNOSTICS_PREFIX+'event_info.state_event_info.index_1').x # Verify - nose.tools.assert_almost_equal(h.x[0], 1.000000, 5, msg="Incorrect initial value for 'h', should be 1.0") - nose.tools.assert_almost_equal(derh.x[0], 0.000000, 5, msg="Incorrect value for 'derh', should be 0.0") + assert h.x[0] == pytest.approx(1.000000, abs = 1e-5), "Incorrect initial value for 'h', should be 1.0" + assert derh.x[0] == pytest.approx(0.000000, abs = 1e-5), "Incorrect value for 'derh', should be 0.0" np.testing.assert_array_equal(ev_ind, np.array([0., 0., 0., 0., 1., 0.])) - @testattr(stddist = True) def test_diagnostics_data_cancelled_simulation_mat_file(self): """ Verify that we can retrieve data and diagnostics data after cancelled sim using matfile. """ self._get_diagnostics_cancelled_sim("TestCancelledSim.mat") - @testattr(stddist = True) def test_diagnostics_data_cancelled_simulation_file_stream(self): """ Verify that we can retrieve data and diagnostics data after cancelled sim using filestream. """ test_file_stream = open('myfilestream.txt', 'wb') self._get_diagnostics_cancelled_sim(test_file_stream) - @testattr(stddist = True) def test_debug_file_not_generated_when_dynamic_diagnostics_is_true(self): """ Verify that the debug file is not created when option dynamic_diagnostics is true. """ model = self._get_bouncing_ball_dummy() @@ -1271,10 +1191,8 @@ def test_debug_file_not_generated_when_dynamic_diagnostics_is_true(self): os.remove(potential_debug_file) model.simulate(options = opts) - nose.tools.assert_false(os.path.isfile(potential_debug_file), - "Test failed, file {} exists after simulation".format(potential_debug_file)) + assert not os.path.isfile(potential_debug_file), "Test failed, file {} exists after simulation".format(potential_debug_file) - @testattr(stddist = True) def test_exception_dynamic_diagnostics_and_non_binary_result_handling(self): """ Verify that an exception is raised if dynamic_diagnostics is True and result_handling is not binary. """ model = self._get_bouncing_ball_dummy() @@ -1284,10 +1202,9 @@ def test_exception_dynamic_diagnostics_and_non_binary_result_handling(self): err_msg = ("The chosen result_handler does not support dynamic_diagnostics." " Try using e.g., ResultHandlerBinaryFile.") - with nose.tools.assert_raises_regex(fmi.InvalidOptionException, err_msg): + with pytest.raises(fmi.InvalidOptionException, match = err_msg): model.simulate(options = opts) - @testattr(stddist = True) def test_exception_dynamic_diagnostics_and_non_binary_result_handling1(self): """ Verify that an exception is raised if dynamic diagnostics is True and result_handling is custom and does not support dynamic_diagnostics. """ @@ -1303,14 +1220,13 @@ def get_result(self): foo_inst = Foo(model) opts["result_handler"] = foo_inst - nose.tools.assert_false(foo_inst.supports.get('dynamic_diagnostics')) + assert not foo_inst.supports.get('dynamic_diagnostics') err_msg = ("The chosen result_handler does not support dynamic_diagnostics." " Try using e.g., ResultHandlerBinaryFile.") - with nose.tools.assert_raises_regex(fmi.InvalidOptionException, err_msg): + with pytest.raises(fmi.InvalidOptionException, match = err_msg): model.simulate(options = opts) - @testattr(stddist = True) def test_exception_dynamic_diagnostics_and_non_binary_result_handling2(self): """ Verify that exception is raised if dynamic diagnostics is True and result_handling is custom and valid class. """ model = self._get_bouncing_ball_dummy() @@ -1329,9 +1245,8 @@ def test_exception_dynamic_diagnostics_and_non_binary_result_handling2(self): exception_msg = str(e) raise e # In case error did not stop the test run - nose.tools.assert_true(no_error, "Error occurred: {}".format(exception_msg)) + assert no_error, "Error occurred: {}".format(exception_msg) - @testattr(stddist = True) def test_custom_result_handler_dynamic_diagnostics(self): """ Test dynamic diagnostics with a custom results handler that supports it. """ model = self._get_bouncing_ball_dummy() @@ -1356,9 +1271,8 @@ def get_result(self): opts["result_handler"] = res_handler model.simulate(options = opts) - nose.tools.assert_true(res_handler.diagnostics_point_called, msg = "diagnostics_point function was never called.") + assert res_handler.diagnostics_point_called, "diagnostics_point function was never called." - @testattr(stddist = True) def test_result_handler_supports_dynamic_diagnostics(self): """ Test dynamic diagnostics with a custom results handler that supports it, but lacks actual implementation. """ model = self._get_bouncing_ball_dummy() @@ -1379,7 +1293,8 @@ def get_result(self): res_handler = ResultDynDiag() opts["result_handler"] = res_handler - nose.tools.assert_raises(NotImplementedError, model.simulate, options = opts) + with pytest.raises(NotImplementedError): + model.simulate(options = opts) def _test_no_debug_file(self, fmu_type): model = self._get_bouncing_ball_dummy(fmu_type=fmu_type) @@ -1392,15 +1307,12 @@ def _test_no_debug_file(self, fmu_type): model.simulate(options = opts) - nose.tools.assert_false(os.path.isfile(expected_debug_file), - msg = f"file {expected_debug_file} found.") + assert not os.path.isfile(expected_debug_file), f"file {expected_debug_file} found." - @testattr(stddist = True) def test_debug_file_not_generated_me1(self): """ Verify that the debug file is not generated by enabling logging (ME1). """ self._test_no_debug_file(fmu_type = 'me1') - @testattr(stddist = True) def test_debug_file_not_generated_me2(self): """ Verify that the debug file is not generated by enabling logging (ME2). """ self._test_no_debug_file(fmu_type = 'me2') @@ -1424,19 +1336,16 @@ def _test_debug_file_opening(self, fmu_type): # Verify with open(expected_debug_file, 'r') as f: line = f.readline() - nose.tools.assert_false(test_str in line, "Test failed, found '{}' in '{}'".format(test_str, line)) + assert not test_str in line, "Test failed, found '{}' in '{}'".format(test_str, line) - @testattr(stddist = True) def test_debug_file_opened_in_write_mode_me1(self): """ Verify that the debug file is opened in write mode if it already did exist (ME1). """ self._test_debug_file_opening(fmu_type = 'me1') - @testattr(stddist = True) def test_debug_file_opened_in_write_mode_me2(self): """ Verify that the debug file is opened in write mode if it already did exist (ME2). """ self._test_debug_file_opening(fmu_type = 'me1') - @testattr(stddist = True) def test_diagnostics_numerical_values(self): """ Verify that we get the expected values for some diagnostics. """ model = self._get_bouncing_ball_dummy() @@ -1451,40 +1360,34 @@ def test_diagnostics_numerical_values(self): expected_solver_order[0] = 0.0 np.testing.assert_array_equal(res[f'{DIAGNOSTICS_PREFIX}solver.solver_order'], expected_solver_order) - @testattr(stddist = True) def test_get_last_result_file0(self): """ Verify get_last_result_file seems to point at the correct file. """ test_model = self._get_bouncing_ball_dummy() file_name = "testname.mat" test_model._result_file = file_name - nose.tools.assert_equal(test_model.get_last_result_file().split(os.sep)[-1], file_name, - "Unable to find {} in string {}".format(file_name, test_model.get_last_result_file())) + assert test_model.get_last_result_file().split(os.sep)[-1] == file_name, "Unable to find {} in string {}".format(file_name, test_model.get_last_result_file()) - @testattr(stddist = True) def test_get_last_result_file1(self): """ Verify get_last_result_file returns an absolute path. """ test_model = self._get_bouncing_ball_dummy() file_name = "testname.mat" test_model._result_file = file_name - nose.tools.assert_true(os.path.isabs(test_model.get_last_result_file()), "Expected abspath but got {}".format(test_model.get_last_result_file())) + assert os.path.isabs(test_model.get_last_result_file()), "Expected abspath but got {}".format(test_model.get_last_result_file()) - @testattr(stddist = True) def test_get_last_result_file2(self): """ Verify get_last_result_file doesnt cause exception if the result file is not yet set. """ test_model = self._get_bouncing_ball_dummy() test_model._result_file = None - nose.tools.assert_true(test_model.get_last_result_file() is None, "Expected None but got {}".format(test_model.get_last_result_file())) + assert test_model.get_last_result_file() is None, "Expected None but got {}".format(test_model.get_last_result_file()) - @testattr(stddist = True) def test_get_last_result_file3(self): """ Verify get_last_result_file doesnt cause exception if the result file is not set correctly. """ test_model = self._get_bouncing_ball_dummy() test_model._result_file = 123 # arbitrary number, just verify get_last_result_file works - nose.tools.assert_true(test_model.get_last_result_file() is None, "Expected None but got {}".format(test_model.get_last_result_file())) + assert test_model.get_last_result_file() is None, "Expected None but got {}".format(test_model.get_last_result_file()) if assimulo_installed: class TestResultCSVTextual_Simulation: - @testattr(stddist = True) def test_only_parameters(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "ParameterAlias.fmu"), _connect_dll=False) @@ -1495,9 +1398,8 @@ def test_only_parameters(self): res = model.simulate(options=opts) - nose.tools.assert_almost_equal(3.0, res["p2"][0]) + assert 3.0 == pytest.approx(res["p2"][0]) - @testattr(stddist = True) def test_no_variables(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "ParameterAlias.fmu"), _connect_dll=False) @@ -1509,11 +1411,9 @@ def test_no_variables(self): res = model.simulate(options=opts) - nose.tools.assert_almost_equal(1.0, res["time"][-1]) + assert 1.0 == pytest.approx(res["time"][-1]) - @testattr(stddist = True) def test_variable_alias_custom_handler(self): - simple_alias = Dummy_FMUModelME1([40], os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "NegatedAlias.fmu"), _connect_dll=False) opts = simple_alias.simulate_options() @@ -1524,38 +1424,32 @@ def test_variable_alias_custom_handler(self): # test that res['y'] returns a vector of the same length as the time # vector - nose.tools.assert_equal(len(res['y']),len(res['time']), - "Wrong size of result vector.") + assert len(res['y']) ==len(res['time']), "Wrong size of result vector." x = res["x"] y = res["y"] for i in range(len(x)): - nose.tools.assert_equal(x[i], -y[i]) + assert x[i] == -y[i] - @testattr(stddist = True) def test_csv_options_me1(self): simple_alias = Dummy_FMUModelME1([40], os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "NegatedAlias.fmu"), _connect_dll=False) _run_negated_alias(simple_alias, "csv") - @testattr(stddist = True) def test_csv_options_me2(self): simple_alias = Dummy_FMUModelME2([("x", "y")], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "NegatedAlias.fmu"), _connect_dll=False) _run_negated_alias(simple_alias, "csv") - @testattr(stddist = True) def test_csv_options_me1_stream(self): simple_alias = Dummy_FMUModelME1([40], os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "NegatedAlias.fmu"), _connect_dll=False) stream = StringIO() _run_negated_alias(simple_alias, "csv", stream) - @testattr(stddist = True) def test_csv_options_me2(self): simple_alias = Dummy_FMUModelME2([("x", "y")], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "NegatedAlias.fmu"), _connect_dll=False) stream = StringIO() _run_negated_alias(simple_alias, "csv", stream) - @testattr(stddist = True) def test_enumeration_csv(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "Friction2.fmu"), _connect_dll=False) @@ -1572,7 +1466,6 @@ def test_enumeration_csv(self): class TestResultCSVTextual: - @testattr(stddist = True) def test_constructor_invalid_stream1(self): """ Verify exception is raised for ResultCSVTextual if filename argument is a stream not supporting 'readline'. """ class A: @@ -1580,10 +1473,9 @@ def seek(self): pass stream = A() msg = "Given stream needs to support 'readline' and 'seek' in order to retrieve the results." - with nose.tools.assert_raises_regex(JIOError, msg): + with pytest.raises(JIOError, match = msg): res = ResultCSVTextual(stream) - @testattr(stddist = True) def test_constructor_invalid_stream2(self): """ Verify exception is raised for ResultCSVTextual if filename argument is a stream not supporting 'seek'. """ class A: @@ -1591,10 +1483,9 @@ def readline(self): pass stream = A() msg = "Given stream needs to support 'readline' and 'seek' in order to retrieve the results." - with nose.tools.assert_raises_regex(JIOError, msg): + with pytest.raises(JIOError, match = msg): res = ResultCSVTextual(stream) - @testattr(stddist = True) def test_delimiter(self): res = ResultCSVTextual(os.path.join(file_path, 'files', 'Results', 'TestCSV.csv'), delimiter=",") @@ -1603,7 +1494,6 @@ def test_delimiter(self): assert x.x[-1] == 1 - @testattr(stddist = True) def _work_flow_me1(self, result_file_name): model = Dummy_FMUModelME1([], os.path.join(file_path, "files", "FMUs", "XML", "ME1.0", "bouncingBall.fmu"), _connect_dll=False) model.initialize() @@ -1624,14 +1514,12 @@ def _work_flow_me1(self, result_file_name): derh = res.get_variable_data('der(h)') g = res.get_variable_data('g') - nose.tools.assert_almost_equal(h.x, 1.000000, 5) - nose.tools.assert_almost_equal(derh.x, 0.000000, 5) + assert h.x == pytest.approx(1.000000, abs = 1e-5) + assert derh.x == pytest.approx(0.000000, abs = 1e-5) - @testattr(stddist = True) def test_work_flow_me1_file(self): self._work_flow_me1('bouncingBall_result.csv') - @testattr(stddist = True) def test_work_flow_me1_stream(self): stream = StringIO() self._work_flow_me1(stream) @@ -1656,37 +1544,30 @@ def _work_flow_me2(self, result_file_name): derh = res.get_variable_data('der(h)') g = res.get_variable_data('g') - nose.tools.assert_almost_equal(h.x, 1.000000, 5) - nose.tools.assert_almost_equal(derh.x, 0.000000, 5) + assert h.x == pytest.approx(1.000000, abs = 1e-5) + assert derh.x == pytest.approx(0.000000, abs = 1e-5) - @testattr(stddist = True) def test_work_flow_me2_file(self): self._work_flow_me2('bouncingBall_result.csv') - @testattr(stddist = True) def test_work_flow_me2_stream(self): stream = StringIO() self._work_flow_me2(stream) - @testattr(stddist = True) def test_work_flow_me2_stream2(self): """ Verify exception when using ResultHandlerCSV with a stream that doesnt support 'write'. """ class A: pass stream = A() # send in something that is not a string msg = "Failed to write the result file. Option 'result_file_name' needs to be a filename or a class that supports writing to through the 'write' method." - with nose.tools.assert_raises_regex(FMUException, msg): + with pytest.raises(FMUException, match = msg): self._work_flow_me2(stream) - """ - @testattr(stddist = True) def test_csv_options_cs1(self): simple_alias = Dummy_FMUModelCS1([40], os.path.join(file_path, "files", "FMUs", "XML", "CS1.0", "NegatedAlias.fmu"), _connect_dll=False) - self._run_negated_alias(self, simple_alias) + _run_negated_alias(simple_alias, "csv") - @testattr(stddist = True) def test_csv_options_cs2(self): simple_alias = Dummy_FMUModelCS2([("x", "y")], os.path.join(file_path, "files", "FMUs", "XML", "CS2.0", "NegatedAlias.fmu"), _connect_dll=False) - self._run_negated_alias(self, simple_alias) - """ + _run_negated_alias(simple_alias, "csv") diff --git a/tests/test_log.py b/tests/test_log.py index 35f112c4..38f26d7d 100644 --- a/tests/test_log.py +++ b/tests/test_log.py @@ -17,7 +17,6 @@ import os -from pyfmi import testattr from pyfmi.common.log import extract_xml_log, parse_xml_log from pyfmi.common.diagnostics import DIAGNOSTICS_PREFIX from pyfmi.tests.test_util import Dummy_FMUModelME2 @@ -28,8 +27,6 @@ logs = os.path.join(file_path, "files", "Logs") class Test_Log: - - @testattr(stddist = True) def test_decode_bytes(self): """ Verifies that malformed strings are still accepted and don't cause exceptions @@ -41,7 +38,6 @@ def test_decode_bytes(self): assert s_string == '[WARNING][FMU status:Warning] "�\x15"', s_string - @testattr(stddist = True) def test_extract_log(self): extract_xml_log("Tmp1.xml", os.path.join(logs, "CoupledClutches_log.txt"), modulename = 'Model') @@ -51,14 +47,12 @@ def test_extract_log(self): assert "" == str(log.nodes[1]), "Got: " + str(log.nodes[1]) - @testattr(stddist = True) def test_extract_log_exception(self): try: extract_xml_log("Tmp2", os.path.join(logs, "CoupledClutches_log_.txt"), modulename = 'Model') except FileNotFoundError: pass - @testattr(stddist = True) def test_extract_log_cs(self): extract_xml_log("Tmp3.xml", os.path.join(logs, "CoupledClutches_CS_log.txt"), modulename = 'Slave') @@ -68,7 +62,6 @@ def test_extract_log_cs(self): assert "" == str(log.nodes[1]), "Got: " + str(log.nodes[1]) - @testattr(stddist = True) def test_extract_log_wrong_modulename(self): extract_xml_log("Tmp4.xml", os.path.join(logs, "CoupledClutches_CS_log.txt"), modulename = 'Test') @@ -100,7 +93,6 @@ def _test_logging_different_solver(self, solver_name): np.testing.assert_equal(len(res['time']), len(res['h']), "Expected time and h to be of equal length but they weren't!") return res - @testattr(stddist = True) def test_logging_option_CVode(self): res = self._test_logging_different_solver("CVode") t = res['time'] @@ -110,30 +102,25 @@ def test_logging_option_CVode(self): assert (f'{DIAGNOSTICS_PREFIX}state_errors.h' in res.keys()), f"'{DIAGNOSTICS_PREFIX}state_errors.h' should be part of result variables!" - @testattr(stddist = True) def test_logging_option_Radau5ODE(self): res = self._test_logging_different_solver("Radau5ODE") event_type = list(res[f'{DIAGNOSTICS_PREFIX}event_data.event_info.event_type']) assert event_type.count(-1) == len(event_type), "Expected no events to have happened!" assert (f'{DIAGNOSTICS_PREFIX}state_errors.h' in res.keys()), f"'{DIAGNOSTICS_PREFIX}state_errors.h' should be part of result variables!" - @testattr(stddist = True) def test_logging_option_ImplicitEuler(self): res = self._test_logging_different_solver("ImplicitEuler") - assert not (f'{DIAGNOSTICS_PREFIX}state_errors.h' in res.keys()), f"'{DIAGNOSTICS_PREFIX}state_errors.h' should not be part of result variables!" + assert f'{DIAGNOSTICS_PREFIX}state_errors.h' not in res.keys(), f"'{DIAGNOSTICS_PREFIX}state_errors.h' should not be part of result variables!" - @testattr(stddist = True) def test_logging_option_ExplicitEuler(self): res = self._test_logging_different_solver("ExplicitEuler") - assert not (f'{DIAGNOSTICS_PREFIX}state_errors.h' in res.keys()), f"'{DIAGNOSTICS_PREFIX}state_errors.h' should not be part of result variables!" + assert f'{DIAGNOSTICS_PREFIX}state_errors.h' not in res.keys(), f"'{DIAGNOSTICS_PREFIX}state_errors.h' should not be part of result variables!" - @testattr(stddist = True) def test_logging_option_LSODAR(self): res = self._test_logging_different_solver("LSODAR") event_type = list(res[f'{DIAGNOSTICS_PREFIX}event_data.event_info.event_type']) assert event_type.count(-1) == len(event_type), "Expected no events to have happened, but event_type contains: {}!".format(event_type) - @testattr(stddist = True) def test_calculated_diagnostic(self): res = self._test_logging_different_solver("CVode") np.testing.assert_equal(len(res['time']), len(res[f'{DIAGNOSTICS_PREFIX}nbr_steps']), @@ -148,14 +135,12 @@ def test_calculated_diagnostic(self): "Expected time and Diagnostics.nbr_state_limits_step.h to be of equal length but they weren't!") - @testattr(stddist = True) def test_extract_boolean_value(self): log = parse_xml_log(os.path.join(logs, "boolean_log.xml")) eis = log.find("EventInfo") for ei in eis: assert isinstance(ei.time_event_info, bool), "Expected ei.time_event_info to be bool" - @testattr(stddist = True) def test_hasattr_works(self): """ Tests that 'hasattr' works on the log nodes. diff --git a/tests/test_stream.py b/tests/test_stream.py index 758c7af1..fd8be522 100644 --- a/tests/test_stream.py +++ b/tests/test_stream.py @@ -15,14 +15,13 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import nose +import pytest import os from io import StringIO import tempfile from shutil import rmtree from filecmp import cmp as compare_files -from pyfmi import testattr from pyfmi.fmi import FMUException, load_fmu, FMUModelCS2, FMUModelME2 from pyfmi.tests.test_util import get_examples_folder @@ -74,31 +73,29 @@ def simulate_and_verify_stream_contents(compiled_fmu, fmu_loader, stream, open_t ] for i, line in enumerate(expected): err_msg = "Unable to find substring {} in list {}".format(line, "".join(contents)) - nose.tools.assert_in(line, contents[i], err_msg) + assert line in contents[i], err_msg class Test_FMUModelME2: """ Test stream functionality for FMI class FMUModelME2. """ + @pytest.fixture(autouse=True) @classmethod def setup_class(cls): cls.example_fmu = os.path.join(get_examples_folder(), 'files', 'FMUs', 'ME2.0', 'bouncingBall.fmu') cls.test_class = FMUModelME2 # Verify the installation is not corrupt while setting up the class. - nose.tools.assert_true(os.path.isfile(cls.example_fmu)) + assert os.path.isfile(cls.example_fmu) - @testattr(stddist = True) def test_testio(self): """ FMUModelME2 and custom IO class. """ stream = TestIO("") simulate_and_verify_stream_contents(self.example_fmu, self.test_class, stream) - @testattr(stddist = True) def test_stringio(self): """ FMUModelME2 and StringIO. """ stream = StringIO() simulate_and_verify_stream_contents(self.example_fmu, self.test_class, stream) - @testattr(stddist = True) def test_textiowrapper(self): """ FMUModelME2 and TextIOWrapper. """ p = tempfile.mkdtemp() @@ -111,27 +108,25 @@ def test_textiowrapper(self): class Test_FMUModelCS2: """ Test stream functionality for FMI class FMUModelCS2. """ + @pytest.fixture(autouse=True) @classmethod def setup_class(cls): cls.example_fmu = os.path.join(get_examples_folder(), 'files', 'FMUs', 'CS2.0', 'bouncingBall.fmu') cls.test_class = FMUModelCS2 # Verify the installation is not corrupt while setting up the class. - nose.tools.assert_true(os.path.isfile(cls.example_fmu)) + assert os.path.isfile(cls.example_fmu) - @testattr(stddist = True) def test_testio(self): """ FMUModelCS2 and custom IO class. """ stream = TestIO("") simulate_and_verify_stream_contents(self.example_fmu, self.test_class, stream) - @testattr(stddist = True) def test_stringio(self): """ FMUModelCS2 and StringIO. """ stream = StringIO() simulate_and_verify_stream_contents(self.example_fmu, self.test_class, stream) - @testattr(stddist = True) def test_textiowrapper(self): """ FMUModelCS2 and TextIOWrapper. """ p = tempfile.mkdtemp() @@ -144,27 +139,25 @@ def test_textiowrapper(self): class Test_LoadFMU: """ Test stream functionality with load_fmu. """ + @pytest.fixture(autouse=True) @classmethod def setup_class(cls): cls.example_fmu = os.path.join(get_examples_folder(), 'files', 'FMUs', 'ME2.0', 'bouncingBall.fmu') cls.test_class = load_fmu # Verify the installation is not corrupt while setting up the class. - nose.tools.assert_true(os.path.isfile(cls.example_fmu)) + assert os.path.isfile(cls.example_fmu) - @testattr(stddist = True) def test_testio(self): """ load_fmu and custom IO class. """ stream = TestIO("") simulate_and_verify_stream_contents(Test_LoadFMU.example_fmu, Test_LoadFMU.test_class, stream) - @testattr(stddist = True) def test_stringio(self): """ load_fmu and StringIO. """ stream = StringIO() simulate_and_verify_stream_contents(Test_LoadFMU.example_fmu, Test_LoadFMU.test_class, stream) - @testattr(stddist = True) def test_textiowrapper(self): """ load_fmu and TextIOWrapper. """ p = tempfile.mkdtemp() @@ -177,14 +170,14 @@ def test_textiowrapper(self): class TestXML: """ Test other log related functions together with streams. """ + @pytest.fixture(autouse=True) @classmethod def setup_class(cls): cls.example_fmu = os.path.join(get_examples_folder(), 'files', 'FMUs', 'ME2.0', 'bouncingBall.fmu') # Verify the installation is not corrupt while setting up the class. - nose.tools.assert_true(os.path.isfile(cls.example_fmu)) + assert os.path.isfile(cls.example_fmu) - @testattr(stddist = True) def test_extract_xml_log(self): """ Compare contents of XML log when using stream and normal logfile. """ stream = TestIO("") @@ -206,9 +199,8 @@ def test_extract_xml_log(self): xml_log = fmu.extract_xml_log() err_msg = "Unequal xml files, please compare the contents of:\n{}\nand\n{}".format(xml_log_s, xml_log) - nose.tools.assert_true(compare_files(xml_log_s, xml_log), err_msg) + assert compare_files(xml_log_s, xml_log), err_msg - @testattr(stddist = True) def test_get_log(self): """ Test get_log throws exception if stream doesnt support getvalue. """ stream = StringIO("") @@ -221,10 +213,9 @@ def test_get_log(self): 'FMIL: module = FMI2XML, log level = 3: fmi2_xml_get_default_experiment_tolerance' ] for i, line in enumerate(expected_substr): - nose.tools.assert_in(line, log[i]) + assert line in log[i] - @testattr(stddist = True) def test_get_log_exception1(self): """ Test get_log throws exception if stream doesnt allow reading (it is set for writing). """ try: @@ -234,7 +225,7 @@ def test_get_log_exception1(self): fmu_s = load_fmu(self.example_fmu, log_file_name = stream, log_level = 3) res_s = fmu_s.simulate() err_msg = "Unable to read from given stream, make sure the stream is readable." - with nose.tools.assert_raises_regex(FMUException, err_msg): + with pytest.raises(FMUException, match = err_msg): log = fmu_s.get_log() finally: if not stream.closed: @@ -242,16 +233,14 @@ def test_get_log_exception1(self): rmtree(p) - @testattr(stddist = True) def test_get_nbr_of_lines_in_log(self): """ Test get_number_of_lines_log when using a stream. """ stream = StringIO("") fmu = load_fmu(self.example_fmu, log_file_name = stream, log_level = 3) - nose.tools.assert_equal(fmu.get_number_of_lines_log(), 0) + assert fmu.get_number_of_lines_log() == 0 res = fmu.simulate() - nose.tools.assert_equal(fmu.get_number_of_lines_log(), 0) + assert fmu.get_number_of_lines_log() == 0 - @testattr(stddist = True) def test_extract_xml_log_into_stream(self): """ Compare contents of XML log when extract XML into a stream. """ stream = TestIO("") @@ -277,4 +266,4 @@ def test_extract_xml_log_into_stream(self): xml_log = fmu.extract_xml_log() err_msg = "Unequal xml files, please compare the contents of:\n{}\nand\n{}".format(xml_file1, xml_log) - nose.tools.assert_true(compare_files(xml_file1, xml_log), err_msg) + assert compare_files(xml_file1, xml_log), err_msg