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

1357 convert unittest to pytest #3931

Closed
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
e5d27fe
Refactor CsvExtractor unit tests for better test independence
ggurjar333 Oct 19, 2024
426bc7f
Refactor unit tests for better test independence
ggurjar333 Oct 26, 2024
f27df16
Refactor unit tests for better test independence
ggurjar333 Oct 26, 2024
f72296c
Merge branch 'catalyst-cooperative:main' into 1357-convert-unittest-t…
ggurjar333 Oct 26, 2024
babf79a
Refactor unit tests for better test independence
ggurjar333 Oct 26, 2024
7eebc13
Merge branch '1357-convert-unittest-to-pytest' of https://github.com/…
ggurjar333 Oct 26, 2024
90ed32c
Refactor unit tests for better test independence
ggurjar333 Oct 26, 2024
378e115
Remove unnecessary IDE configuration files
ggurjar333 Oct 26, 2024
dd0d66d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 26, 2024
da43e14
Refactor excel_test.py for better test independence
ggurjar333 Oct 27, 2024
4b485a1
Merge branch '1357-convert-unittest-to-pytest' of https://github.com/…
ggurjar333 Oct 27, 2024
291d6af
Refactor excel_test.py for better test independence
ggurjar333 Oct 27, 2024
79fb818
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 27, 2024
35c472b
Refactor excel_test.py for better test independence
ggurjar333 Oct 27, 2024
ce806ca
Refactor excel_test.py for better test perfomance
ggurjar333 Oct 27, 2024
b1fc12e
Refactor excel_test.py for better test independance
ggurjar333 Oct 27, 2024
cb4014c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 27, 2024
e124ee9
Refactor classes_test.py for improved test organization
ggurjar333 Oct 31, 2024
6aba44d
Merge branch '1357-convert-unittest-to-pytest' of https://github.com/…
ggurjar333 Oct 31, 2024
202c3ff
Merge branch 'main' into 1357-convert-unittest-to-pytest
ggurjar333 Oct 31, 2024
e98a8ce
Refactor mocks in classes_test.py for improved readability
ggurjar333 Nov 1, 2024
b512458
Convert unittest assertions to pytest style in resource_cache_test.py
ggurjar333 Nov 2, 2024
dd41e1f
Convert unittest assertions to pytest style in resource_cache_test.py
ggurjar333 Nov 2, 2024
fbd2950
Convert unittest assertions to pytest style in resource_cache_test.py
ggurjar333 Nov 2, 2024
4c0b5c9
Merge branch 'main' into 1357-convert-unittest-to-pytest
ggurjar333 Nov 2, 2024
946f2d0
Merge branch 'main' into 1357-convert-unittest-to-pytest
ggurjar333 Nov 6, 2024
601c18e
Merge branch 'main' into 1357-convert-unittest-to-pytest
zaneselvans Nov 8, 2024
eac3ac9
Merge branch 'main' into 1357-convert-unittest-to-pytest
ggurjar333 Nov 9, 2024
bc9464c
Merge branch 'main' into 1357-convert-unittest-to-pytest
zaneselvans Nov 14, 2024
361bbe3
Refactor tests in csv_test.py to use pytest and simplify mock handling
ggurjar333 Nov 20, 2024
3715646
Merge branch 'main' into 1357-convert-unittest-to-pytest
ggurjar333 Nov 20, 2024
7c0b992
Merge branch '1357-convert-unittest-to-pytest' of https://github.com/…
ggurjar333 Nov 20, 2024
be984f5
Refactor excel_test.py to use pytest fixtures for metadata and extrac…
ggurjar333 Nov 21, 2024
1831e59
Refactor phsmsagas_test.py to use pytest fixtures and improve mock ha…
ggurjar333 Nov 21, 2024
a5cdad0
Refactor tests in ferc1_test.py to use pytest fixtures and enhance mo…
ggurjar333 Nov 21, 2024
cecc003
Refactor resource_cache_test.py to use pytest class methods for setup…
ggurjar333 Nov 22, 2024
474902f
Refactor datastore_test.py to use class method for setup in TestZenod…
ggurjar333 Nov 22, 2024
e71dcaa
Refactor csv_test.py to use mocker for CsvExtractor and clean up exce…
ggurjar333 Dec 3, 2024
07a59ec
Merge branch 'main' into 1357-convert-unittest-to-pytest
ggurjar333 Dec 14, 2024
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
74 changes: 30 additions & 44 deletions test/unit/extract/csv_test.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
"""Unit tests for pudl.extract.csv module."""

from unittest.mock import MagicMock, patch

import pandas as pd
import pytest

Expand All @@ -16,16 +12,16 @@


class FakeExtractor(CsvExtractor):
def __init__(self):
def __init__(self, mocker):
ggurjar333 marked this conversation as resolved.
Show resolved Hide resolved
# TODO: Make these tests independent of the eia176 implementation
self.METADATA = GenericMetadata("eia176")
super().__init__(ds=MagicMock())
super().__init__(ds=mocker.MagicMock())


@pytest.fixture
def extractor():
# Create an instance of the CsvExtractor class
return FakeExtractor()
def extractor(mocker):
# Create an instance of the CsvExtractor class with mocker
return FakeExtractor(mocker)


def test_source_filename_valid_partition(extractor):
Expand All @@ -45,8 +41,8 @@ def test_source_filename_multiple_selections(extractor):
extractor.source_filename(PAGE, **multiple_selections)


@patch("pudl.extract.csv.pd")
def test_load_source(mock_pd, extractor):
def test_load_source(mocker, extractor):
mock_pd = mocker.patch("pudl.extract.csv.pd")
assert extractor.load_source(PAGE, **PARTITION) == mock_pd.read_csv.return_value
extractor.ds.get_zipfile_resource.assert_called_once_with(DATASET, **PARTITION)
zipfile = extractor.ds.get_zipfile_resource.return_value.__enter__.return_value
Expand All @@ -55,7 +51,7 @@ def test_load_source(mock_pd, extractor):
mock_pd.read_csv.assert_called_once_with(file)


def test_extract(extractor):
def test_extract(mocker, extractor):
# Create a sample of data we could expect from an EIA CSV
company_field = "company"
company_data = "Total of All Companies"
Expand All @@ -64,34 +60,30 @@ def test_extract(extractor):

# TODO: Once FakeExtractor is independent of eia176, mock out populating _column_map for PARTITION_SELECTION;
# Also include negative tests, i.e., for partition selections not in the _column_map
with (
patch.object(CsvExtractor, "load_source", return_value=df),
patch.object(
# Testing the rename
GenericMetadata,
"get_column_map",
return_value={"company_rename": company_field},
),
patch.object(
# Transposing the df here to get the orientation we expect get_page_cols to return
CsvExtractor,
"get_page_cols",
return_value=df.T.index,
),
):
res = extractor.extract(**PARTITION)
mocker.patch.object(CsvExtractor, "load_source", return_value=df)
ggurjar333 marked this conversation as resolved.
Show resolved Hide resolved
# Testing the rename
mocker.patch.object(
GenericMetadata,
"get_column_map",
return_value={"company_rename": company_field},
)
# Transposing the df here to get the orientation we expect get_page_cols to return
mocker.patch.object(
CsvExtractor,
"get_page_cols",
return_value=df.T.index,
)
res = extractor.extract(**PARTITION)
assert len(res) == 1 # Assert only one page extracted
assert list(res.keys()) == [PAGE] # Assert it is named correctly
assert (
res[PAGE][company_field][0] == company_data
) # Assert that column correctly renamed and data is there.


@patch.object(FakeExtractor, "METADATA")
def test_validate_exact_columns(mock_metadata, extractor):
def test_validate_exact_columns(mocker, extractor):
ggurjar333 marked this conversation as resolved.
Show resolved Hide resolved
# Mock the partition selection and page columns
# mock_metadata._get_partition_selection.return_value = "partition1"
extractor.get_page_cols = MagicMock(return_value={"col1", "col2"})
extractor.get_page_cols = mocker.MagicMock(return_value={"col1", "col2"})

# Create a DataFrame with the exact expected columns
df = pd.DataFrame(columns=["col1", "col2"])
Expand All @@ -100,11 +92,9 @@ def test_validate_exact_columns(mock_metadata, extractor):
extractor.validate(df, "page1", partition="partition1")


@patch.object(FakeExtractor, "METADATA")
def test_validate_extra_columns(mock_metadata, extractor):
def test_validate_extra_columns(mocker, extractor):
# Mock the partition selection and page columns
mock_metadata._get_partition_selection.return_value = "partition1"
extractor.get_page_cols = MagicMock(return_value={"col1", "col2"})
extractor.get_page_cols = mocker.MagicMock(return_value={"col1", "col2"})

# Create a DataFrame with extra columns
df = pd.DataFrame(columns=["col1", "col2", "col3"])
Expand All @@ -114,11 +104,9 @@ def test_validate_extra_columns(mock_metadata, extractor):
extractor.validate(df, "page1", partition="partition1")


@patch.object(FakeExtractor, "METADATA")
def test_validate_missing_columns(mock_metadata, extractor):
def test_validate_missing_columns(mocker, extractor):
# Mock the partition selection and page columns
mock_metadata._get_partition_selection.return_value = "partition1"
extractor.get_page_cols = MagicMock(return_value={"col1", "col2"})
extractor.get_page_cols = mocker.MagicMock(return_value={"col1", "col2"})

# Create a DataFrame with missing columns
df = pd.DataFrame(columns=["col1"])
Expand All @@ -130,11 +118,9 @@ def test_validate_missing_columns(mock_metadata, extractor):
extractor.validate(df, "page1", partition="partition1")


@patch.object(FakeExtractor, "METADATA")
def test_validate_extra_and_missing_columns(mock_metadata, extractor):
def test_validate_extra_and_missing_columns(mocker, extractor):
# Mock the partition selection and page columns
mock_metadata._get_partition_selection.return_value = "partition1"
extractor.get_page_cols = MagicMock(return_value={"col1", "col2"})
extractor.get_page_cols = mocker.MagicMock(return_value={"col1", "col2"})

# Create a DataFrame with both extra and missing columns
df = pd.DataFrame(columns=["col1", "col3"])
Expand Down
54 changes: 30 additions & 24 deletions test/unit/extract/excel_test.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,42 @@
"""Unit tests for pudl.extract.excel module."""

import unittest
from unittest import mock as mock

import pandas as pd
import pytest

from pudl.extract import excel


class TestMetadata(unittest.TestCase):
class TestMetadata:
"""Tests basic operation of the excel.Metadata object."""

@pytest.fixture(autouse=True)
ggurjar333 marked this conversation as resolved.
Show resolved Hide resolved
def setUp(self):
"""Cosntructs test metadata instance for testing."""
"""Constructs test metadata instance for testing."""
self._metadata = excel.ExcelMetadata("test")

def test_basics(self):
"""Test that basic API method return expected results."""
self.assertEqual("test", self._metadata.get_dataset_name())
self.assertListEqual(
["books", "boxes", "shoes"], self._metadata.get_all_pages()
)
self.assertListEqual(
["author", "pages", "title"], self._metadata.get_all_columns("books")
)
self.assertDictEqual(
{"book_title": "title", "name": "author", "pages": "pages"},
self._metadata.get_column_map("books", year=2010),
)
self.assertEqual(10, self._metadata.get_skiprows("boxes", year=2011))
self.assertEqual(1, self._metadata.get_sheet_name("boxes", year=2011))
assert self._metadata.get_dataset_name() == "test"
assert self._metadata.get_all_pages() == ["books", "boxes", "shoes"]
assert self._metadata.get_all_columns("books") == ["author", "pages", "title"]
assert self._metadata.get_column_map("books", year=2010) == {
"book_title": "title",
"name": "author",
"pages": "pages",
}
assert self._metadata.get_skiprows("boxes", year=2011) == 10
assert self._metadata.get_sheet_name("boxes", year=2011) == 1

def test_metadata_methods(self):
"""Test various metadata methods."""
assert self._metadata.get_all_columns("books") == ["author", "pages", "title"]
assert self._metadata.get_column_map("books", year=2010) == {
"book_title": "title",
"name": "author",
"pages": "pages",
}
assert self._metadata.get_skiprows("boxes", year=2011) == 10
assert self._metadata.get_sheet_name("boxes", year=2011) == 1


class FakeExtractor(excel.ExcelExtractor):
Expand Down Expand Up @@ -77,11 +84,10 @@ def _fake_data_frames(page_name, **kwargs):
return fake_data[page_name]


class TestExtractor(unittest.TestCase):
class TestExtractor:
"""Test operation of the excel.Extractor class."""

@staticmethod
def test_extract():
def test_extract(self):
extractor = FakeExtractor()
res = extractor.extract(year=[2010, 2011])
expected_books = {
Expand All @@ -103,7 +109,7 @@ def test_extract():
# def test_resulting_dataframes(self):
# """Checks that pages across years are merged and columns are translated."""
# dfs = FakeExtractor().extract([2010, 2011], testing=True)
# self.assertEqual(set(['books', 'boxes']), set(dfs.keys()))
# assert set(['books', 'boxes']) == set(dfs.keys())
ggurjar333 marked this conversation as resolved.
Show resolved Hide resolved
# pd.testing.assert_frame_equal(
# pd.DataFrame(data={
# 'author': ['Laozi', 'Benjamin Hoff'],
Expand All @@ -118,5 +124,5 @@ def test_extract():
# }),
# dfs['boxes'])

# TODO([email protected]): need to figure out how to test process_$x methods.
# TODO([email protected]): we should test that empty columns are properly added.
# TODO: need to figure out how to test process_$x methods.
# TODO: we should test that empty columns are properly added.
28 changes: 13 additions & 15 deletions test/unit/extract/phmsagas_test.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from unittest.mock import MagicMock, patch

import pandas as pd
import pytest

Expand All @@ -8,20 +6,20 @@


class FakeExtractor(Extractor):
def __init__(self):
def __init__(self, mocker):
ggurjar333 marked this conversation as resolved.
Show resolved Hide resolved
self.METADATA = ExcelMetadata("phmsagas")
super().__init__(ds=MagicMock())
self._metadata = MagicMock()
super().__init__(ds=mocker.Mock())
self._metadata = mocker.Mock()


@pytest.fixture
def extractor():
def extractor(mocker):
# Create an instance of the CsvExtractor class
return FakeExtractor()
return FakeExtractor(mocker)


@patch("pudl.extract.phmsagas.logger")
def test_process_renamed_drop_columns(mock_logger, extractor):
def test_process_renamed_drop_columns(mocker, extractor):
mock_logger = mocker.patch("pudl.extract.phmsagas.logger")
ggurjar333 marked this conversation as resolved.
Show resolved Hide resolved
# Mock metadata methods
extractor._metadata.get_form.return_value = "gas_transmission_gathering"
extractor._metadata.get_all_columns.return_value = ["col1", "col2"]
Expand All @@ -38,8 +36,8 @@ def test_process_renamed_drop_columns(mock_logger, extractor):
mock_logger.info.assert_called_once()


@patch("pudl.extract.phmsagas.logger")
def test_process_renamed_keep_columns(mock_logger, extractor):
def test_process_renamed_keep_columns(mocker, extractor):
mock_logger = mocker.patch("pudl.extract.phmsagas.logger")
# Mock metadata methods
extractor._metadata.get_form.return_value = "gas_transmission_gathering"
extractor._metadata.get_all_columns.return_value = ["col1", "col2"]
Expand All @@ -56,8 +54,8 @@ def test_process_renamed_keep_columns(mock_logger, extractor):
mock_logger.info.assert_not_called()


@patch("pudl.extract.phmsagas.logger")
def test_process_renamed_drop_unnamed_columns(mock_logger, extractor):
def test_process_renamed_drop_unnamed_columns(mocker, extractor):
mock_logger = mocker.patch("pudl.extract.phmsagas.logger")
# Mock metadata methods
extractor._metadata.get_form.return_value = "some_form"
extractor._metadata.get_all_columns.return_value = ["col1", "col2"]
Expand All @@ -74,8 +72,8 @@ def test_process_renamed_drop_unnamed_columns(mock_logger, extractor):
mock_logger.warning.assert_not_called()


@patch("pudl.extract.phmsagas.logger")
def test_process_renamed_warn_unnamed_columns(mock_logger, extractor):
def test_process_renamed_warn_unnamed_columns(mocker, extractor):
mock_logger = mocker.patch("pudl.extract.phmsagas.logger")
# Mock metadata methods
extractor._metadata.get_form.return_value = "some_form"
extractor._metadata.get_all_columns.return_value = ["col1", "col2"]
Expand Down
20 changes: 13 additions & 7 deletions test/unit/output/ferc1_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
"""

import logging
import unittest
from io import StringIO

import networkx as nx
Expand All @@ -37,10 +36,8 @@
logger = logging.getLogger(__name__)


class TestForestSetup(unittest.TestCase):
def setUp(self):
# this is where you add nodes you want to use
pass
class TestForestSetup:
"""Base class for forest testing."""

def _exploded_calcs_from_edges(self, edges: list[tuple[NodeId, NodeId]]):
records = []
Expand Down Expand Up @@ -90,7 +87,9 @@ def build_forest_and_annotated_tags(


class TestPrunnedNode(TestForestSetup):
def setUp(self):
@pytest.fixture(autouse=True)
ggurjar333 marked this conversation as resolved.
Show resolved Hide resolved
def setup_nodes(self):
"""Setup nodes for testing."""
self.root = NodeId(
table_name="table_1",
xbrl_factoid="reported_1",
Expand Down Expand Up @@ -121,6 +120,7 @@ def setUp(self):
)

def test_pruned_nodes(self):
"""Test pruned nodes."""
edges = [(self.root, self.root_child), (self.root_other, self.root_other_child)]
tags = pd.DataFrame(columns=list(NodeId._fields)).convert_dtypes()
forest = XbrlCalculationForestFerc1(
Expand All @@ -133,7 +133,11 @@ def test_pruned_nodes(self):


class TestTagPropagation(TestForestSetup):
def setUp(self):
"""Test tag propagation functionality."""

@pytest.fixture(autouse=True)
ggurjar333 marked this conversation as resolved.
Show resolved Hide resolved
def setup_nodes(self):
"""Setup nodes for testing."""
self.parent = NodeId(
table_name="table_1",
xbrl_factoid="reported_1",
Expand Down Expand Up @@ -185,6 +189,7 @@ def setUp(self):
)

def test_leafward_prop_undecided_children(self):
"""Test leadward propagation with undecided children."""
ggurjar333 marked this conversation as resolved.
Show resolved Hide resolved
ggurjar333 marked this conversation as resolved.
Show resolved Hide resolved
edges = [(self.parent, self.child1), (self.parent, self.child2)]
tags = pd.DataFrame([self.parent, self.child1, self.child2]).assign(
in_rate_base=["yes", pd.NA, pd.NA]
Expand Down Expand Up @@ -369,6 +374,7 @@ def test_annotated_forest_propagates_rootward_two_layers_plus_corrections(self):


def test_get_core_ferc1_asset_description():
"""Test core FERC1 asset description extraction."""
valid_core_ferc1_asset_name = "core_ferc1__yearly_income_statements_sched114"
valid_core_ferc1_asset_name_result = get_core_ferc1_asset_description(
valid_core_ferc1_asset_name
Expand Down
Loading