Becksteinlab / kda

Python package used for the analysis of biochemical kinetic diagrams.
GNU General Public License v3.0
5 stars 1 forks source link

MAINT, TST: hypothesis FailedHealthCheck error due to multiple executors #76

Closed nawtrey closed 1 year ago

nawtrey commented 1 year ago

Description

When running tests locally in a fresh Python 3.9 environment I'm getting a FailedHealthCheck error:

================================== FAILURES ===================================
_ Test_Misc_Funcs.test_thermo_force_4WL[cycle1-cycle_order1-log(k12*k24*k41/(k14*k21*k42))] _
[gw3] win32 -- Python 3.9.17 C:\Users\nikol\.conda\envs\kda-env-py39\python.exe

self = <kda.tests.test_kda.Test_Misc_Funcs object at 0x00000248AF0703D0>
cycle = [0, 3, 1], cycle_order = [3, 0]
expected_func = 'log(k12*k24*k41/(k14*k21*k42))'

    @settings(deadline=None)
>   @given(
        k_vals=st.lists(
            st.floats(min_value=1, max_value=100), min_size=10, max_size=10
        ),
    )
E   hypothesis.errors.FailedHealthCheck: The method Test_Misc_Funcs.test_thermo_force_4WL was called from multiple different executors. This may lead to flaky tests and nonreproducible errors when replaying from database.
E   See https://hypothesis.readthedocs.io/en/latest/healthchecks.html for more information about this. If you want to disable just this health check, add HealthCheck.differing_executors to the suppress_health_check settings for this test.

kda\tests\test_kda.py:973: FailedHealthCheck
=========================== short test summary info ===========================
FAILED kda/tests/test_kda.py::Test_Misc_Funcs::test_thermo_force_4WL[cycle1-cycle_order1-log(k12*k24*k41/(k14*k21*k42))]
======================== 1 failed, 63 passed in 25.81s ========================

This appears to be the result of using @given() with @pytest.mark.parametrize() on a pytest that takes a while to complete for each iteration. I believe the issue is it has to execute the hypothesis strategy multiple times which raises a flag at run time.

Possible Solution(s)

There are a few possible solutions to this:

  1. deactivate the health check using @settings(suppress_health_check=[HealthCheck.differing_executors])
  2. iterate over the various cycles and function inside the test
  3. move away from using @given() for this test

I think the first solution is probably the best since it keeps the test running many different arrays for each cycle case. The test does take longer to run than it probably should because of the parametrization, but it runs all 3 test cases in ~4 seconds, so that's fine for now. Unfortunately it will raise an error on the Python 3.7 CI runner since HealthCheck.differing_executors is not present for the older versions of hypothesis, but I think it may be worth finding a solution for that (maybe even removing Python 3.7) to maintain the rigor of the test.