Skip to content

Commit a44ebce

Browse files
committed
Move report table mocks into fixture.
1 parent 9de3a44 commit a44ebce

File tree

1 file changed

+92
-173
lines changed

1 file changed

+92
-173
lines changed

tests/manager/reporting/reports/test_library_collection.py

Lines changed: 92 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import logging
22
import zipfile
3-
from contextlib import closing
3+
from contextlib import closing, contextmanager
44
from datetime import datetime, timedelta
55
from io import BytesIO
66
from pathlib import Path
@@ -339,7 +339,7 @@ def report_table_call(processor):
339339
result = report._process_table(mock_table)
340340

341341
assert result.table_key == "test-table"
342-
assert result.filename == "palace-test_table_id-default-2024-01-01T12-00-00.csv"
342+
assert result.filename == "palace-test-table-default-2024-01-01T12-00-00.csv"
343343
assert result.row_count == 2
344344
assert hasattr(result.content_stream, "read")
345345

@@ -494,7 +494,7 @@ def test_store_package_failure(
494494

495495
with pytest.raises(
496496
IntegrationException,
497-
match=r"Failed to store report 'test_report' for library 'default' \(default\) to S3.",
497+
match=r"Failed to store report 'test-report' for library 'default' \(default\) to S3.",
498498
):
499499
report._store_package(package)
500500

@@ -592,25 +592,18 @@ def test_initialize_tables(
592592
)
593593

594594

595-
class IntegrationLibraryCollectionReportFixture(LibraryCollectionReportFixture):
595+
class LibraryCollectionReportRunFixture(LibraryCollectionReportFixture):
596+
596597
class MockLibraryCollectionReport(LibraryCollectionReport):
597598
KEY = "test-report"
598599
TITLE = "Test Report"
600+
# Note: No _run_report override - uses real implementation
599601

602+
def __init__(self, db: DatabaseTransactionFixture):
603+
super().__init__(db)
600604

601-
@pytest.fixture
602-
def integration_report_fixture(
603-
db: DatabaseTransactionFixture,
604-
) -> LibraryCollectionReportFixture:
605-
return IntegrationLibraryCollectionReportFixture(db)
606-
607-
608-
class TestLibraryCollectionRun:
609-
610-
def test_run_success(
611-
self,
612-
integration_report_fixture: LibraryCollectionReportFixture,
613-
):
605+
def create_mock_table(self, *, should_fail: bool = False):
606+
"""Create a mock table class and instance for testing."""
614607
mock_table_class = MagicMock()
615608
mock_table_instance = MagicMock(spec=ReportTable)
616609
mock_definition = MagicMock(
@@ -622,42 +615,62 @@ def test_run_success(
622615
return_value=mock_definition
623616
)
624617

625-
def table_call(processor):
626-
test_rows = [("header1", "header2"), ("data1", "data2")]
627-
counted_rows, _ = processor(rows=test_rows[1:], headings=test_rows[0])
628-
return counted_rows, None
618+
if should_fail:
619+
exception = ValueError("Table processing failed")
620+
mock_table_instance.side_effect = exception
621+
else:
622+
623+
def table_call(processor):
624+
test_rows = [("data1", "data2"), ("data3", "data4")]
625+
headings = ["col1", "col2"]
626+
counted_rows, _ = processor(rows=test_rows, headings=headings)
627+
return counted_rows, None
628+
629+
mock_table_instance.side_effect = table_call
629630

630-
mock_table_instance.side_effect = table_call
631631
mock_table_class.return_value = mock_table_instance
632+
return mock_table_class
633+
634+
@contextmanager
635+
def with_mock_table(self, *, should_fail: bool = False):
636+
"""Context manager that sets up a mock table and patches TABLE_CLASSES."""
637+
mock_table_class = self.create_mock_table(should_fail=should_fail)
632638

633639
with patch.object(
634-
integration_report_fixture.MockLibraryCollectionReport,
640+
self.MockLibraryCollectionReport,
635641
"TABLE_CLASSES",
636642
[mock_table_class],
637643
):
638-
report = integration_report_fixture.report
644+
yield mock_table_class
639645

640-
expected_url = "https://s3.example.com/reports/test-report.zip"
641-
integration_report_fixture.s3_service.store_stream.return_value = (
642-
expected_url
643-
)
644646

645-
success = report.run(session=integration_report_fixture.db.session)
647+
@pytest.fixture
648+
def report_run_fixture(
649+
db: DatabaseTransactionFixture,
650+
) -> LibraryCollectionReportRunFixture:
651+
return LibraryCollectionReportRunFixture(db)
646652

647-
assert success is True
648653

649-
assert report.library == integration_report_fixture.db.default_library()
654+
class TestLibraryCollectionRun:
655+
656+
def test_run_full_integration(
657+
self,
658+
report_run_fixture: LibraryCollectionReportRunFixture,
659+
):
660+
with report_run_fixture.with_mock_table():
661+
report = report_run_fixture.report
662+
expected_url = "https://s3.example.com/reports/test-report.zip"
663+
report_run_fixture.s3_service.store_stream.return_value = expected_url
664+
success = report.run(session=report_run_fixture.db.session)
665+
666+
assert success is True
667+
assert report.library == report_run_fixture.db.default_library()
650668
assert report.timestamp is not None
651669

652-
mock_table_class.assert_called_once_with(
653-
session=integration_report_fixture.db.session,
654-
library_id=integration_report_fixture.db.default_library().id,
655-
collection_ids=None,
656-
)
670+
report_run_fixture.s3_service.store_stream.assert_called_once()
671+
report_run_fixture.send_email.assert_called_once()
657672

658-
integration_report_fixture.s3_service.store_stream.assert_called_once()
659-
integration_report_fixture.send_email.assert_called_once()
660-
email_args = integration_report_fixture.send_email.call_args[1]
673+
email_args = report_run_fixture.send_email.call_args[1]
661674
assert email_args["receivers"] == report.email_address
662675
assert (
663676
"Palace report 'Test Report' for library 'default'"
@@ -668,36 +681,18 @@ def table_call(processor):
668681

669682
def test_run_table_processing_failure(
670683
self,
671-
integration_report_fixture: LibraryCollectionReportFixture,
684+
report_run_fixture: LibraryCollectionReportRunFixture,
672685
caplog: pytest.LogCaptureFixture,
673686
):
674687
caplog.set_level(logging.ERROR)
675688

676-
mock_table_class = MagicMock()
677-
mock_table_instance = MagicMock(spec=ReportTable)
678-
mock_definition = MagicMock(
679-
spec=TabularQueryDefinition,
680-
key="test-table",
681-
title="Test Table",
682-
)
683-
type(mock_table_instance).definition = PropertyMock(
684-
return_value=mock_definition
685-
)
686-
mock_table_instance.side_effect = ValueError("Table processing failed")
687-
mock_table_class.return_value = mock_table_instance
688-
689-
with patch.object(
690-
integration_report_fixture.MockLibraryCollectionReport,
691-
"TABLE_CLASSES",
692-
[mock_table_class],
693-
):
694-
695-
report = integration_report_fixture.report
696-
success = report.run(session=integration_report_fixture.db.session)
689+
with report_run_fixture.with_mock_table(should_fail=True):
690+
report = report_run_fixture.report
691+
success = report.run(session=report_run_fixture.db.session)
697692

698693
assert success is False
699-
integration_report_fixture.send_email.assert_called_once()
700-
email_args = integration_report_fixture.send_email.call_args[1]
694+
report_run_fixture.send_email.assert_called_once()
695+
email_args = report_run_fixture.send_email.call_args[1]
701696
assert report.email_address == email_args["receivers"]
702697
assert (
703698
"Palace report 'Test Report' for library 'default'"
@@ -711,45 +706,20 @@ def test_run_table_processing_failure(
711706

712707
def test_run_packaging_failure(
713708
self,
714-
integration_report_fixture: LibraryCollectionReportFixture,
709+
report_run_fixture: LibraryCollectionReportRunFixture,
715710
caplog: pytest.LogCaptureFixture,
716711
):
717712
caplog.set_level(logging.ERROR)
718713

719-
mock_table_class = MagicMock()
720-
mock_table_instance = MagicMock(spec=ReportTable)
721-
mock_definition = MagicMock(
722-
spec=TabularQueryDefinition,
723-
key="test-table",
724-
title="Test Table",
725-
)
726-
type(mock_table_instance).definition = PropertyMock(
727-
return_value=mock_definition
728-
)
729-
730-
def table_call(processor):
731-
counted_rows, _ = processor(
732-
rows=[("data1", "data2")], headings=["col1", "col2"]
733-
)
734-
return counted_rows, None
735-
736-
mock_table_instance.side_effect = table_call
737-
mock_table_class.return_value = mock_table_instance
738-
739-
with patch.object(
740-
integration_report_fixture.MockLibraryCollectionReport,
741-
"TABLE_CLASSES",
742-
[mock_table_class],
743-
):
744-
report = integration_report_fixture.report
745-
746-
with patch.object(report, "_package_results") as mock_store_package:
747-
mock_store_package.side_effect = ValueError("It didn't work.")
748-
success = report.run(session=integration_report_fixture.db.session)
714+
with report_run_fixture.with_mock_table():
715+
report = report_run_fixture.report
716+
with patch.object(report, "_package_results") as mock_packaging:
717+
mock_packaging.side_effect = ValueError("Packaging failed")
718+
success = report.run(session=report_run_fixture.db.session)
749719

750720
assert success is False
751-
integration_report_fixture.send_email.assert_called_once()
752-
email_args = integration_report_fixture.send_email.call_args[1]
721+
report_run_fixture.send_email.assert_called_once()
722+
email_args = report_run_fixture.send_email.call_args[1]
753723
assert report.email_address == email_args["receivers"]
754724
assert (
755725
"Palace report 'Test Report' for library 'default'"
@@ -763,46 +733,19 @@ def table_call(processor):
763733

764734
def test_run_s3_storage_failure(
765735
self,
766-
integration_report_fixture: LibraryCollectionReportFixture,
736+
report_run_fixture: LibraryCollectionReportRunFixture,
767737
caplog: pytest.LogCaptureFixture,
768738
):
769739
caplog.set_level(logging.ERROR)
770740

771-
mock_table_class = MagicMock()
772-
mock_table_instance = MagicMock(spec=ReportTable)
773-
mock_definition = MagicMock(
774-
spec=TabularQueryDefinition,
775-
key="test-table",
776-
title="Test Table",
777-
)
778-
type(mock_table_instance).definition = PropertyMock(
779-
return_value=mock_definition
780-
)
781-
782-
def table_call(processor):
783-
counted_rows, _ = processor(
784-
rows=[("data1", "data2")], headings=["col1", "col2"]
785-
)
786-
return counted_rows, None
787-
788-
mock_table_instance.side_effect = table_call
789-
mock_table_class.return_value = mock_table_instance
790-
791-
with patch.object(
792-
integration_report_fixture.MockLibraryCollectionReport,
793-
"TABLE_CLASSES",
794-
[mock_table_class],
795-
):
796-
report = integration_report_fixture.report
797-
798-
integration_report_fixture.s3_service.store_stream.return_value = None
799-
800-
success = report.run(session=integration_report_fixture.db.session)
741+
with report_run_fixture.with_mock_table():
742+
report = report_run_fixture.report
743+
report_run_fixture.s3_service.store_stream.return_value = None
744+
success = report.run(session=report_run_fixture.db.session)
801745

802746
assert success is False
803-
804-
integration_report_fixture.send_email.assert_called_once()
805-
email_args = integration_report_fixture.send_email.call_args[1]
747+
report_run_fixture.send_email.assert_called_once()
748+
email_args = report_run_fixture.send_email.call_args[1]
806749
assert report.email_address == email_args["receivers"]
807750
assert (
808751
"Palace report 'Test Report' for library 'default'"
@@ -819,25 +762,23 @@ def table_call(processor):
819762

820763
def test_run_library_not_found(
821764
self,
822-
integration_report_fixture: LibraryCollectionReportFixture,
765+
report_run_fixture: LibraryCollectionReportRunFixture,
823766
caplog: pytest.LogCaptureFixture,
824767
):
825768
caplog.set_level(logging.ERROR)
826769

827-
report = integration_report_fixture.MockLibraryCollectionReport(
828-
send_email=integration_report_fixture.send_email,
829-
s3_service=integration_report_fixture.s3_service,
770+
report = report_run_fixture.MockLibraryCollectionReport(
771+
send_email=report_run_fixture.send_email,
772+
s3_service=report_run_fixture.s3_service,
830773
request_id="test_request_id",
831774
library_id=999999,
832775
email_address="[email protected]",
833776
)
834-
835-
success = report.run(session=integration_report_fixture.db.session)
777+
success = report.run(session=report_run_fixture.db.session)
836778

837779
assert success is False
838-
839-
integration_report_fixture.send_email.assert_called_once()
840-
email_args = integration_report_fixture.send_email.call_args[1]
780+
report_run_fixture.send_email.assert_called_once()
781+
email_args = report_run_fixture.send_email.call_args[1]
841782
assert report.email_address == email_args["receivers"]
842783
assert (
843784
"Palace report 'Test Report' for an unknown library"
@@ -855,52 +796,30 @@ def test_run_library_not_found(
855796

856797
def test_run_with_collection_ids(
857798
self,
858-
integration_report_fixture: LibraryCollectionReportFixture,
799+
report_run_fixture: LibraryCollectionReportRunFixture,
859800
):
860-
collection1 = integration_report_fixture.db.collection()
861-
collection2 = integration_report_fixture.db.collection()
801+
collection1 = report_run_fixture.db.collection()
802+
collection2 = report_run_fixture.db.collection()
862803
collection_ids = [collection1.id, collection2.id]
863804

864-
report = integration_report_fixture.MockLibraryCollectionReport(
865-
send_email=integration_report_fixture.send_email,
866-
s3_service=integration_report_fixture.s3_service,
805+
report = report_run_fixture.MockLibraryCollectionReport(
806+
send_email=report_run_fixture.send_email,
807+
s3_service=report_run_fixture.s3_service,
867808
request_id="test_request_id",
868-
library_id=integration_report_fixture.db.default_library().id,
809+
library_id=report_run_fixture.db.default_library().id,
869810
collection_ids=collection_ids,
870811
email_address="[email protected]",
871812
)
872813

873-
mock_table_class = MagicMock()
874-
mock_table_instance = MagicMock(spec=ReportTable)
875-
mock_definition = MagicMock(
876-
spec=TabularQueryDefinition, key="test-table", title="Test Table"
877-
)
878-
type(mock_table_instance).definition = PropertyMock(
879-
return_value=mock_definition
880-
)
881-
882-
def table_call(processor):
883-
counted_rows, _ = processor(rows=[("data",)], headings=["col1"])
884-
return counted_rows, None
885-
886-
mock_table_instance.side_effect = table_call
887-
mock_table_class.return_value = mock_table_instance
888-
889-
with patch.object(
890-
integration_report_fixture.MockLibraryCollectionReport,
891-
"TABLE_CLASSES",
892-
[mock_table_class],
893-
):
894-
integration_report_fixture.s3_service.store_stream.return_value = (
814+
with report_run_fixture.with_mock_table() as mock_table_class:
815+
report_run_fixture.s3_service.store_stream.return_value = (
895816
"https://s3.example.com/test.zip"
896817
)
897-
898-
success = report.run(session=integration_report_fixture.db.session)
818+
success = report.run(session=report_run_fixture.db.session)
899819

900820
assert success is True
901-
902821
mock_table_class.assert_called_once_with(
903-
session=integration_report_fixture.db.session,
904-
library_id=integration_report_fixture.db.default_library().id,
822+
session=report_run_fixture.db.session,
823+
library_id=report_run_fixture.db.default_library().id,
905824
collection_ids=collection_ids,
906825
)

0 commit comments

Comments
 (0)