import time import pytest from pytest import approx from tests import helpers from tests.util import logger, ReportRun, Split WAIT_TIME_SECS = 10 TEST_RUNS = [ # NOTE: split rates are percentages # MANUAL report cases ReportRun( trigger_type="MANUAL", expected_error_count=0, splits=[ Split(type="NET", rate=60), Split(type="NET", rate=30), Split(type="NET", rate=10), Split(type="GROSS", rate=0), ], ), # AUTO report cases # 1. Gross split ReportRun( trigger_type="AUTO", expected_error_count=1, splits=[ Split(type="GROSS", rate=0), ], ), # 2. Single split >100% ReportRun( trigger_type="AUTO", expected_error_count=1, splits=[ Split(type="NET", rate=120), ], ), # 3. Splits adding to >100% ReportRun( trigger_type="AUTO", expected_error_count=2, splits=[ Split(type="NET", rate=90), Split(type="NET", rate=90), ], ), # Success ReportRun( trigger_type="AUTO", expected_error_count=0, splits=[ Split(type="NET", rate=60), Split(type="NET", rate=30), Split(type="NET", rate=10), ], ), ] def _trigger_report_run(run: ReportRun, config, collaborators_conn, art_relations_conn, sqs_client): test_name = helpers.get_test_name() logger.info("Creating collaborators") collaborators = helpers.create_collaborators(collaborators_conn, config, test_name, run.splits) # Create splits for collaborators tuids = helpers.get_tracks_for_vendor(art_relations_conn, config) logger.info(f"Creating splits for {len(tuids)} tracks") helpers.create_splits(collaborators_conn, collaborators, tuids) # Create report run and report for collaborator report_run_uuid = helpers.get_report_run_uuid() run.report_run_uuid = report_run_uuid logger.info(f"Creating report run with UUID: {report_run_uuid}") helpers.create_report_run( collaborators_conn, config, report_run_uuid, collaborators, test_name, trigger_type=run.trigger_type, ) # Trigger report generation logger.info("Triggering report generation") helpers.trigger_report_generation(sqs_client, report_run_uuid) def _is_run_pending(run: ReportRun, collaborators_conn): logger.info(f"Checking if {run.report_run_uuid} is pending results") # Wait for invalid reports to error error_count = run.expected_error_count if ( len(helpers.get_reports_with_status(collaborators_conn, run.report_run_uuid, "ERROR")) != error_count ): return True # Wait for valid reports to generate generated_count = len(run.splits) - error_count if ( len( reports := helpers.get_reports_with_status( collaborators_conn, run.report_run_uuid, "GENERATED" ) ) != generated_count ): return True run.reports = reports @pytest.mark.timeout(600) # 10 minutes @pytest.mark.parametrize("run", TEST_RUNS) def test_report_gen( run: ReportRun, config, collaborators_conn, art_relations_conn, snowflake_conn, sqs_client ): logger.info(config) # Insert an open statement period if it doesn't exist already logger.info("Creating open statement period for vendor (if none exists)") helpers.create_statement_period_if_not_exists(collaborators_conn, config) # Delete existing splits for vendor logger.info("Deleting existing splits for vendor") helpers.delete_existing_splits(collaborators_conn, config) # First trigger the run _trigger_report_run(run, config, collaborators_conn, art_relations_conn, sqs_client) # Wait for the run to complete while _is_run_pending(run, collaborators_conn): logger.info(f"Report is pending. Waiting for {WAIT_TIME_SECS} seconds...") time.sleep(WAIT_TIME_SECS) # Check the results of the run expected_error_count = run.expected_error_count expected_generated_count = len(run.splits) - expected_error_count logger.info(f"Report run {run.report_run_uuid} is complete") if len(run.reports) == 0 and expected_generated_count == 0: logger.info("This run generated no reports, as expected") return for report in run.reports: logger.info( f"Report for collaborator {report['collaborator_id']}: " f"{report['amount']} {report['currency']}" ) # Fetch total for statement period from Snowflake logger.info("Fetching total for statement period from Snowflake") vendor_fact_sales_sum = helpers.get_vendor_fact_sales_sum(snowflake_conn, config) report_run_total = sum(report["amount"] for report in run.reports) logger.info(f"Report run total: {report_run_total} {run.reports[0]['currency']}") logger.info( f"Snowflake total: {vendor_fact_sales_sum['AMOUNT']} {vendor_fact_sales_sum['CURRENCY']}" ) # Check total is correct assert report_run_total == approx(vendor_fact_sales_sum["AMOUNT"], abs=0.001)