Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upversioned dependencies and fixed testing strategy #142

Merged
merged 8 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/python-app.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up Python 3.9
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: 3.9
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install wheel
pip install flake8 pytest pandas pydotplus IPython colorutils networkx
pip install flake8 pytest pandas pydotplus IPython colorutils
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Test with pytest
run: |
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,6 @@ data/tic-tac-toe.xlsx
cegpy-binder
docs/_build/*
.mypy
build
build
.venv
venv
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ scipy>=1.7.0
colorutils>=0.3.0
xlsxwriter>=3.0.0
tox>=4.2.8
networkx>=3.2.1
4 changes: 2 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ classifiers =
package_dir =
= src
packages = find:
python_requires = >=3.6
python_requires= >=3.9
install_requires =
pandas >=1.3.0
pydotplus >=2.0.2
ipython >=7.25.0
scipy >=1.7.0
colorutils >=0.3.0
networkx >=2.6.3
networkx >=3.2.1

license_files=
LICENSE
Expand Down
16 changes: 7 additions & 9 deletions src/tests/test_ceg.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,26 @@
# pylint: disable=protected-access
import re
from pathlib import Path
from typing import Dict, List, Mapping, Tuple
from typing import Dict, Mapping
import unittest
from unittest.mock import Mock, patch
import networkx as nx
import pandas as pd
import pytest
import pytest_mock
from cegpy import StagedTree, ChainEventGraph
from cegpy.graphs._ceg import (
CegAlreadyGenerated,
_merge_edge_data,
)


class TestMockedCEGMethods:
class TestMockedCEGMethods(unittest.TestCase):
"""Tests that Mock functions in ChainEventGraph"""

node_prefix = "w"
sink_suffix = "∞"
staged: StagedTree

def setup(self):
def setUp(self):
"""Test setup"""
df_path = (
Path(__file__)
Expand All @@ -34,12 +32,12 @@ def setup(self):
self.staged = StagedTree(dataframe=pd.read_excel(df_path))
self.staged.calculate_AHC_transitions()

def test_generate_argument(self, mocker: pytest_mock.MockerFixture):
@patch("cegpy.graphs._ceg.ChainEventGraph.generate", autospec=True)
def test_generate_argument(self, generate_mock: Mock):
"""When ChainEventGraph called with generate, the .generate()
method is called."""
mocker.patch("cegpy.graphs._ceg.ChainEventGraph.generate")
ceg = ChainEventGraph(self.staged, generate=True)
ceg.generate.assert_called_once() # pylint: disable=no-member
ChainEventGraph(self.staged, generate=True)
generate_mock.assert_called_once() # pylint: disable=no-member


class TestUnitCEG(unittest.TestCase):
Expand Down
4 changes: 2 additions & 2 deletions src/tests/test_ceg_reducer.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,8 +443,8 @@ def test_str_out(self):
assert str(node) in str_rep


class TestReducedCEGTwo(object):
def setup(self):
class TestReducedCEGTwo(unittest.TestCase):
def setUp(self):
G = nx.MultiDiGraph()
self.init_nodes = ["w0", "w1", "w2", "w3", "w4", "w5", "w6", "w_infinity"]
self.init_edges = [
Expand Down
95 changes: 51 additions & 44 deletions src/tests/test_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ def test_incorrect_sampling_zero_fails(self):
)


class TestEventTree:
def setup(self):
class TestEventTree(unittest.TestCase):
def setUp(self):
df_path = (
Path(__file__)
.resolve()
Expand Down Expand Up @@ -148,8 +148,8 @@ def test_node_colours(self) -> None:
assert event_node_colours[0] == "lightgrey"


class TestIntegration:
def setup(self):
class TestIntegration(unittest.TestCase):
def setUp(self):
# stratified dataset
med_df_path = (
Path(__file__)
Expand Down Expand Up @@ -198,8 +198,8 @@ def check_list_contains_strings(str_list) -> bool:
assert isinstance(elem, str)


class TestUsecase:
def setup(self):
class TestUsecase(unittest.TestCase):
def setUp(self):
# stratified dataset
med_df_path = (
Path(__file__)
Expand Down Expand Up @@ -232,88 +232,95 @@ def test_fall_cats_per_var(self):


class TestChangingDataFrame:
def setup(self):
@pytest.fixture
def med_df(self):
# stratified dataset
med_df_path = (
Path(__file__)
.resolve()
.parent.parent.joinpath("../data/medical_dm_modified.xlsx")
)
self.med_s_z_paths = None
self.med_df = pd.read_excel(med_df_path)
self.med_et = EventTree(
dataframe=self.med_df, sampling_zero_paths=self.med_s_z_paths
)

return pd.read_excel(med_df_path)

@pytest.fixture
def med_et(self, med_df):
med_s_z_paths = None
med_et = EventTree(dataframe=med_df, sampling_zero_paths=med_s_z_paths)
return med_et

@pytest.fixture
def fall_df(self):
# non-stratified dataset
fall_df_path = (
Path(__file__).resolve().parent.parent.joinpath("../data/Falls_Data.xlsx")
)
return pd.read_excel(fall_df_path)

@pytest.fixture
def fall_et(self, fall_df):
self.fall_s_z_paths = None
self.fall_df = pd.read_excel(fall_df_path)
self.fall_et = EventTree(
dataframe=self.fall_df, sampling_zero_paths=self.fall_s_z_paths
)
return EventTree(dataframe=fall_df, sampling_zero_paths=self.fall_s_z_paths)

def test_add_empty_column(self) -> None:
def test_add_empty_column(self, fall_et, med_df, med_et, fall_df) -> None:
# adding empty column
med_empty_column_df = self.med_df
med_empty_column_df = med_df
med_empty_column_df["extra"] = ""
med_empty_column_et = EventTree(dataframe=med_empty_column_df)
assert med_empty_column_et.adj == self.med_et.adj
assert med_empty_column_et.adj == med_et.adj

fall_empty_column_df = self.fall_df
fall_empty_column_df = fall_df
fall_empty_column_df["extra"] = ""
fall_empty_column_et = EventTree(dataframe=fall_empty_column_df)
assert fall_empty_column_et.adj == self.fall_et.adj
assert fall_empty_column_et.adj == fall_et.adj

def test_add_NA_column(self) -> None:
def test_add_NA_column(self, fall_et, med_df, med_et, fall_df) -> None:
# adding NA column
med_add_NA_df = self.med_df
med_add_NA_df = med_df
med_add_NA_df["extra"] = np.nan
med_add_NA_et = EventTree(dataframe=med_add_NA_df)
assert med_add_NA_et.adj == self.med_et.adj
assert med_add_NA_et.adj == med_et.adj

fall_add_NA_df = self.fall_df
fall_add_NA_df = fall_df
fall_add_NA_df["extra"] = np.nan
fall_add_NA_et = EventTree(dataframe=fall_add_NA_df)
assert fall_add_NA_et.adj == self.fall_et.adj
assert fall_add_NA_et.adj == fall_et.adj

def test_add_same_column(self) -> None:
def test_add_same_column(self, fall_et, med_df, med_et, fall_df) -> None:
# adding column with no more information
med_add_same_df = self.med_df
med_add_same_df = med_df
med_add_same_df["extra"] = "same for all"
med_add_same_et = EventTree(dataframe=med_add_same_df)
assert len(med_add_same_et.leaves) == len(self.med_et.leaves)
assert len(med_add_same_et.leaves) == len(med_et.leaves)

fall_add_same_df = self.fall_df
fall_add_same_df = fall_df
fall_add_same_df["extra"] = "same for all"
fall_add_same_et = EventTree(dataframe=fall_add_same_df)
assert len(fall_add_same_et.leaves) == len(self.fall_et.leaves)
assert len(fall_add_same_et.leaves) == len(fall_et.leaves)

def test_add_same_column_int(self) -> None:
def test_add_same_column_int(self, fall_et, med_df, med_et, fall_df) -> None:
# adding column with no more information
med_add_same_df = self.med_df
med_add_same_df = med_df
med_add_same_df["extra"] = 1
med_add_same_et = EventTree(dataframe=med_add_same_df)
try:
med_add_same_et.create_figure("et_fig_path.pdf")
except InvocationException:
pass
assert len(med_add_same_et.leaves) == len(self.med_et.leaves)
assert len(med_add_same_et.leaves) == len(med_et.leaves)

fall_add_same_df = self.fall_df
fall_add_same_df = fall_df
fall_add_same_df["extra"] = 1
fall_add_same_et = EventTree(dataframe=fall_add_same_df)
try:
fall_add_same_et.create_figure("et_fig_path.pdf")
except InvocationException:
pass
assert len(fall_add_same_et.leaves) == len(self.fall_et.leaves)
assert len(fall_add_same_et.leaves) == len(fall_et.leaves)


class TestMissingLabels:
def setup(self):
class TestMissingLabels(unittest.TestCase):
def setUp(self):
array = [
np.array(["1", "NotANum", "Recover"]),
np.array(["1", "Trt1", "NotANum"]),
Expand Down Expand Up @@ -525,8 +532,8 @@ def test_complete_case_reduction(self) -> None:
assert df_et.dataframe.equals(expected_df) is True


class TestVariablesFiltered:
def setup(self):
class TestVariablesFiltered(unittest.TestCase):
def setUp(self):
array = [
np.array(["1", "NotANum", "Recover"]),
np.array(["1", "Trt1", "NotANum"]),
Expand All @@ -535,7 +542,7 @@ def setup(self):
np.array(["1", "Trt1", "Recover"]),
np.array(["1", "Trt2", "Recover"]),
np.array(["1", "Trt2", "Dont Recover"]),
np.array(["1", np.NaN, "Dont Recover"]),
np.array(["1", np.nan, "Dont Recover"]),
]

self.df = pd.DataFrame(array)
Expand All @@ -562,8 +569,8 @@ def test_pd_nans_filtered_with_missing(self) -> None:
assert df_et.categories_per_variable == expected_categories


class TestStageColours:
def setup(self):
class TestStageColours(unittest.TestCase):
def setUp(self):
array = [
np.array(["1", "NotANum", "Recover"]),
np.array(["1", "Trt1", "NotANum"]),
Expand All @@ -572,7 +579,7 @@ def setup(self):
np.array(["1", "Trt1", "Recover"]),
np.array(["1", "Trt2", "Recover"]),
np.array(["1", "Trt2", "Dont Recover"]),
np.array(["1", np.NaN, "Dont Recover"]),
np.array(["1", np.nan, "Dont Recover"]),
]

self.df = pd.DataFrame(array)
Expand Down
30 changes: 8 additions & 22 deletions src/tests/test_staged.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,23 @@
class TestLogging:
"""Tests logging in stagedtree"""

def setup(self):
"""Test setup"""
# pylint: disable=attribute-defined-outside-init
# stratified dataset
@pytest.fixture
def med_st(self):
med_df_path = (
Path(__file__)
.resolve()
.parent.parent.joinpath("../data/medical_dm_modified.xlsx")
)
self.med_s_z_paths = None
self.med_df = pd.read_excel(med_df_path)
self.med_st = StagedTree(
dataframe=self.med_df, sampling_zero_paths=self.med_s_z_paths
)

# non-stratified dataset
fall_df_path = (
Path(__file__).resolve().parent.parent.joinpath("../data/Falls_Data.xlsx")
)
self.fall_s_z_paths = None
self.fall_df = pd.read_excel(fall_df_path)
self.fall_st = StagedTree(
dataframe=self.fall_df,
sampling_zero_paths=self.fall_s_z_paths,
)
med_s_z_paths = None
med_df = pd.read_excel(med_df_path)
med_st = StagedTree(dataframe=med_df, sampling_zero_paths=med_s_z_paths)
return med_st

def test_run_ahc_before_figure(self) -> None:
def test_run_ahc_before_figure(self, med_st) -> None:
"""Tests expected error message is in the log when running without
running AHC"""
try:
self.med_st.create_figure()
med_st.create_figure()

except (InvocationException):
pass
Expand Down
Loading