Skip to content

Commit

Permalink
Qa/logging tap tester (singer-io#190)
Browse files Browse the repository at this point in the history
*using tap-tester logger

* remove singer import

* appease Dylan (PR feedback)

* fix attr window test - broken with previous change

* update field selection test

* fix invalid attr window and start date tests

Co-authored-by: kspeer <kspeer@stitchdata.com>
  • Loading branch information
2 people authored and jesuejunior committed Mar 17, 2023
1 parent 55aeb41 commit 8834dd1
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 48 deletions.
25 changes: 18 additions & 7 deletions tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from datetime import timedelta
from datetime import datetime as dt

import singer
from tap_tester import connections, menagerie, runner
from tap_tester.logger import LOGGER


class FacebookBaseTest(unittest.TestCase):
Expand All @@ -29,7 +29,6 @@ class FacebookBaseTest(unittest.TestCase):
FULL_TABLE = "FULL_TABLE"
START_DATE_FORMAT = "%Y-%m-%dT00:00:00Z"
BOOKMARK_COMPARISON_FORMAT = "%Y-%m-%dT00:00:00+00:00"
LOGGER = singer.get_logger()

start_date = ""

Expand Down Expand Up @@ -216,7 +215,7 @@ def run_and_verify_check_mode(self, conn_id):
found_catalog_names = set(map(lambda c: c['stream_name'], found_catalogs))

self.assertSetEqual(self.expected_streams(), found_catalog_names, msg="discovered schemas do not match")
print("discovered schemas are OK")
LOGGER.info("discovered schemas are OK")

return found_catalogs

Expand All @@ -240,7 +239,7 @@ def run_and_verify_sync(self, conn_id):
sum(sync_record_count.values()), 0,
msg="failed to replicate any data: {}".format(sync_record_count)
)
print("total replicated row count: {}".format(sum(sync_record_count.values())))
LOGGER.info("total replicated row count: %s", sum(sync_record_count.values()))

return sync_record_count

Expand Down Expand Up @@ -270,7 +269,7 @@ def perform_and_verify_table_and_field_selection(self,

# Verify all testable streams are selected
selected = catalog_entry.get('annotated-schema').get('selected')
print("Validating selection on {}: {}".format(cat['stream_name'], selected))
LOGGER.info("Validating selection on %s: %s", cat['stream_name'], selected)
if cat['stream_name'] not in expected_selected:
self.assertFalse(selected, msg="Stream selected, but not testable.")
continue # Skip remaining assertions if we aren't selecting this stream
Expand All @@ -280,8 +279,8 @@ def perform_and_verify_table_and_field_selection(self,
# Verify all fields within each selected stream are selected
for field, field_props in catalog_entry.get('annotated-schema').get('properties').items():
field_selected = field_props.get('selected')
print("\tValidating selection on {}.{}: {}".format(
cat['stream_name'], field, field_selected))
LOGGER.info("\tValidating selection on %s.%s: %s",
cat['stream_name'], field, field_selected)
self.assertTrue(field_selected, msg="Field not selected.")
else:
# Verify only automatic fields are selected
Expand Down Expand Up @@ -363,3 +362,15 @@ def timedelta_formatted(self, dtime, days=0):
@staticmethod
def is_insight(stream):
return stream.startswith('ads_insights')

def setUp(self):
LOGGER.info("-------------------------------------------- STARTING TEST ---------------------------------------------------")
LOGGER.info("test: %s", self.name())
LOGGER.info("streams covered: %s", self.streams_to_test())
LOGGER.info("--------------------------------------------------------------------------------------------------------------")

def tearDown(self):
LOGGER.info("--------------------------------------------- ENDING TEST ----------------------------------------------------")
LOGGER.info("test: %s", self.name())
LOGGER.info("streams covered: %s", self.streams_to_test())
LOGGER.info("--------------------------------------------------------------------------------------------------------------")
7 changes: 5 additions & 2 deletions tests/test_facebook_archived_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ class FacebookArchivedData(FacebookBaseTest):
def name():
return "tap_tester_facebook_archived_data"

def streams_to_test(self):
"""include_deleted is supported for below streams only"""
return ['ads', 'adsets', 'campaigns']

def get_properties(self, original: bool = True):
"""Configuration properties required for the tap."""
return_value = {
Expand All @@ -29,8 +33,7 @@ def test_run(self):
'''
Testing the archived data with 'include_deleted' parameter
'''
# include_deleted is supported for below streams only
expected_streams = ['ads', 'adsets', 'campaigns']
expected_streams = self.streams_to_test()

##########################################################################
### First Sync with include_deleted = false
Expand Down
27 changes: 14 additions & 13 deletions tests/test_facebook_attribution_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@

from base import FacebookBaseTest


class FacebookAttributionWindow(FacebookBaseTest):

@staticmethod
def name():
return "tap_tester_facebook_attribution_window"

def streams_to_test(self):
""" 'attribution window' is only supported for 'ads_insights' streams """
return [stream for stream in self.expected_streams() if self.is_insight(stream)]

def get_properties(self, original: bool = True):
"""Configuration properties required for the tap."""
return_value = {
Expand All @@ -24,8 +29,11 @@ def get_properties(self, original: bool = True):
return_value["start_date"] = self.start_date
return return_value

# For the test ad set up in facebook ads manager we see data on April 7th, start date is based on this data
def test_run(self):
"""
For the test ad set up in facebook ads manager we see data
on April 7th, start date is based on this data
"""
# attrribution window = 7
self.ATTRIBUTION_WINDOW = 7
self.start_date = '2021-04-14T00:00:00Z'
Expand All @@ -44,30 +52,23 @@ def test_run(self):
self.end_date = '2021-04-09T00:00:00Z'
self.run_test(self.ATTRIBUTION_WINDOW, self.start_date, self.end_date)


def run_test(self, attr_window, start_date, end_date):
"""
Test to check the attribution window
"""

expected_streams = self.streams_to_test()

conn_id = connections.ensure_connection(self)

# calculate start date with attribution window
start_date_with_attribution_window = self.timedelta_formatted(start_date, days=-attr_window)

# 'attribution window' is only supported for 'ads_insights' streams
expected_insights_streams = []
for stream in self.expected_streams():
if self.is_insight(stream):
expected_insights_streams.append(stream)

# core streams does not respect start date so will be descoped from this test

# # Run in check mode
# Run in check mode
found_catalogs = self.run_and_verify_check_mode(conn_id)

# Select only the expected streams tables
catalog_entries = [ce for ce in found_catalogs if ce['tap_stream_id'] in expected_insights_streams]
catalog_entries = [ce for ce in found_catalogs if ce['tap_stream_id'] in expected_streams]
self.perform_and_verify_table_and_field_selection(conn_id, catalog_entries, select_all_fields=True)

# Run a sync job using orchestrator
Expand All @@ -76,7 +77,7 @@ def run_test(self, attr_window, start_date, end_date):

expected_replication_keys = self.expected_replication_keys()

for stream in expected_insights_streams:
for stream in expected_streams:
with self.subTest(stream=stream):

replication_key = next(iter(expected_replication_keys[stream]))
Expand Down
5 changes: 4 additions & 1 deletion tests/test_facebook_automatic_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ class FacebookAutomaticFields(FacebookBaseTest):
def name():
return "tap_tester_facebook_automatic_fields"

def streams_to_test(self):
return self.expected_streams()

def get_properties(self, original: bool = True):
"""Configuration properties required for the tap."""
return_value = {
Expand All @@ -41,7 +44,7 @@ def test_run(self):
that 251 (or more) records have been posted for that stream.
"""

expected_streams = self.expected_streams()
expected_streams = self.streams_to_test()

# instantiate connection
conn_id = connections.ensure_connection(self)
Expand Down
5 changes: 4 additions & 1 deletion tests/test_facebook_bookmarks.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ class FacebookBookmarks(FacebookBaseTest):
def name():
return "tap_tester_facebook_bookmarks"

def streams_to_test(self):
return self.expected_streams()

def get_properties(self, original: bool = True):
"""Configuration properties required for the tap."""
return_value = {
Expand Down Expand Up @@ -96,7 +99,7 @@ def is_expected_date_format(self, date):
return True

def test_run(self):
expected_streams = self.expected_streams()
expected_streams = self.streams_to_test()
non_insight_streams = {stream for stream in expected_streams if not self.is_insight(stream)}
insight_streams = {stream for stream in expected_streams if self.is_insight(stream)}

Expand Down
6 changes: 4 additions & 2 deletions tests/test_facebook_discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@

class DiscoveryTest(FacebookBaseTest):
"""Test tap discovery mode and metadata conforms to standards."""

@staticmethod
def name():
return "tap_tester_facebook_discovery_test"

def streams_to_test(self):
return self.expected_streams()

def test_run(self):
"""
Testing that discovery creates the appropriate catalog with valid metadata.
Expand All @@ -30,7 +32,7 @@ def test_run(self):
are given the inclusion of automatic.
• verify that all other fields have inclusion of available metadata.
"""
streams_to_test = self.expected_streams()
streams_to_test = self.streams_to_test()

conn_id = connections.ensure_connection(self)

Expand Down
26 changes: 6 additions & 20 deletions tests/test_facebook_field_selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def name():
return "tap_tester_facebook_field_selection"

@staticmethod
def expected_check_streams():
def streams_to_test():
return {
'ads',
'adcreative',
Expand All @@ -29,23 +29,6 @@ def expected_check_streams():
#'leads',
}

@staticmethod
def expected_sync_streams():
return {
"ads",
"adcreative",
"adsets",
"campaigns",
"ads_insights",
"ads_insights_age_and_gender",
"ads_insights_country",
"ads_insights_platform_and_device",
"ads_insights_region",
"ads_insights_dma",
"ads_insights_hourly_advertiser",
#"leads",
}

@staticmethod
def expected_pks():
return {
Expand Down Expand Up @@ -76,6 +59,9 @@ def get_properties(self): # pylint: disable=arguments-differ
}

def test_run(self):

expected_streams = self.streams_to_test()

conn_id = connections.ensure_connection(self)

# run in check mode
Expand All @@ -90,7 +76,7 @@ def test_run(self):

found_catalog_names = set(map(lambda c: c['tap_stream_id'], found_catalogs))

diff = self.expected_check_streams().symmetric_difference( found_catalog_names )
diff = expected_streams.symmetric_difference( found_catalog_names )
self.assertEqual(len(diff), 0, msg="discovered schemas do not match: {}".format(diff))
print("discovered schemas are kosher")

Expand Down Expand Up @@ -118,7 +104,7 @@ def test_run(self):
menagerie.verify_sync_exit_status(self, exit_status, sync_job_name)

# This should be validating the the PKs are written in each record
record_count_by_stream = runner.examine_target_output_file(self, conn_id, self.expected_sync_streams(), self.expected_pks())
record_count_by_stream = runner.examine_target_output_file(self, conn_id, expected_streams, self.expected_pks())
replicated_row_count = reduce(lambda accum,c : accum + c, record_count_by_stream.values())
self.assertGreater(replicated_row_count, 0, msg="failed to replicate any data: {}".format(record_count_by_stream))
print("total replicated row count: {}".format(replicated_row_count))
Expand Down
6 changes: 5 additions & 1 deletion tests/test_facebook_invalid_attribution_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ class FacebookInvalidAttributionWindowInt(FacebookBaseTest):
def name():
return "tt_facebook_invalid_window_int"

@staticmethod
def streams_to_test():
return []

def get_properties(self, original: bool = True):
"""Configuration properties required for the tap."""
return_value = {
Expand All @@ -31,7 +35,7 @@ def test_run(self):

def run_test(self):
"""
Test to verify that the error is raise when passing attribution window other than 1, 7 or 28
Test to verify that the error is raise when passing attribution window other than 1, 7 or 28
"""
# create connection
conn_id = connections.ensure_connection(self)
Expand Down
5 changes: 4 additions & 1 deletion tests/test_facebook_start_date.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ class FacebookStartDateTest(FacebookBaseTest):
def name():
return "tap_tester_facebook_start_date_test"

def streams_to_test(self):
return self.expected_streams()

def get_properties(self, original: bool = True):
"""Configuration properties required for the tap."""
return_value = {
Expand All @@ -36,7 +39,7 @@ def test_run(self):

self.start_date = self.start_date_1

expected_streams = self.expected_streams()
expected_streams = self.streams_to_test()

##########################################################################
### First Sync
Expand Down

0 comments on commit 8834dd1

Please sign in to comment.