-
Notifications
You must be signed in to change notification settings - Fork 141
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
TDL-7596: Add tap-tester test for attribution window #169
Changes from all commits
295ab53
484c41a
fec4797
655f945
1bf6960
a698010
23a7e4a
0fa3b4c
46b2832
2edfbc8
fae3e78
d21d8d0
713d9e0
cc24a23
064d3af
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import os | ||
|
||
from tap_tester import runner, connections | ||
|
||
from base import FacebookBaseTest | ||
|
||
class FacebookAttributionWindow(FacebookBaseTest): | ||
|
||
# set attribution window | ||
ATTRIBUTION_WINDOW = 7 | ||
|
||
@staticmethod | ||
def name(): | ||
return "tap_tester_facebook_attribution_window" | ||
|
||
def get_properties(self, original: bool = True): | ||
"""Configuration properties required for the tap.""" | ||
return_value = { | ||
'account_id': os.getenv('TAP_FACEBOOK_ACCOUNT_ID'), | ||
'start_date' : '2019-07-24T00:00:00Z', | ||
'end_date' : '2019-07-26T00:00:00Z', | ||
'insights_buffer_days': str(self.ATTRIBUTION_WINDOW) | ||
} | ||
if original: | ||
return return_value | ||
|
||
return_value["start_date"] = self.start_date | ||
return return_value | ||
|
||
def test_run(self): | ||
self.run_test(self.ATTRIBUTION_WINDOW) # attribution window: 7 | ||
|
||
self.ATTRIBUTION_WINDOW = 28 | ||
self.run_test(self.ATTRIBUTION_WINDOW) # attribution window: 28 | ||
|
||
def run_test(self, attr_window): | ||
""" | ||
Test to check the attribution window | ||
""" | ||
|
||
conn_id = connections.ensure_connection(self) | ||
|
||
# get start date | ||
start_date = self.get_properties()['start_date'] | ||
# 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_streams = [] | ||
for stream in self.expected_streams(): | ||
if self.is_insight(stream): | ||
expected_streams.append(stream) | ||
|
||
# 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_streams] | ||
self.perform_and_verify_table_and_field_selection(conn_id, catalog_entries, select_all_fields=True) | ||
|
||
# Run a sync job using orchestrator | ||
self.run_and_verify_sync(conn_id) | ||
sync_records = runner.get_records_from_target_output() | ||
|
||
expected_replication_keys = self.expected_replication_keys() | ||
|
||
for stream in expected_streams: | ||
with self.subTest(stream=stream): | ||
|
||
replication_key = next(iter(expected_replication_keys[stream])) | ||
|
||
# get records | ||
records = [record.get('data') for record in sync_records.get(stream).get('messages')] | ||
|
||
# check for the record is between attribution date and start date | ||
is_between = False | ||
|
||
for record in records: | ||
replication_key_value = record.get(replication_key) | ||
|
||
# Verify the sync records respect the (simulated) start date value | ||
self.assertGreaterEqual(self.parse_date(replication_key_value), self.parse_date(start_date_with_attribution_window), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @harshpatel4crest Can you please explain how does the 3 checks asked in the DoD of this ticket is accumulated in this test case? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
3rd check is about the error message when we pass the attribution window other than {1, 7, 28}. But the UI does not allow the attribution window to be set except {1, 7, 28}. The tap is also working when we set an attribution window other than this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please complete the 3rd assertion. If the tap does not throw an acceptable error, that is a bug and should be documented and linked in the test with a workaround. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Facebook only supports those values, so even though the tap does not blow up when given a different value I think we should force an error so that we match what they claim they support. Additionally we have use cases where the tap is ran directly so, just because the UI has restrictions around the values does not mean a user will not send something crazy into the config. FB Docs: https://www.facebook.com/business/help/395050428485124?id=428636648170202 Stitch Docs: https://www.stitchdata.com/docs/integrations/saas/facebook-ads#select-attribution-window There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @kspeer825 Added code change to raise an error when the attribution window is not 1, 7 or 28. |
||
msg="The record does not respect the attribution window.") | ||
|
||
# verify if the record's bookmark value is between start date and (simulated) start date value | ||
if self.parse_date(start_date_with_attribution_window) <= self.parse_date(replication_key_value) < self.parse_date(start_date): | ||
is_between = True | ||
|
||
self.assertTrue(is_between, msg="No record found between start date and attribution date.") |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import os | ||
|
||
from tap_tester import runner, connections, menagerie | ||
|
||
from base import FacebookBaseTest | ||
|
||
class FacebookInvalidAttributionWindow(FacebookBaseTest): | ||
|
||
@staticmethod | ||
def name(): | ||
return "tap_tester_facebook_invalid_attribution_window" | ||
|
||
def get_properties(self, original: bool = True): | ||
"""Configuration properties required for the tap.""" | ||
return_value = { | ||
'account_id': os.getenv('TAP_FACEBOOK_ACCOUNT_ID'), | ||
'start_date' : '2019-07-24T00:00:00Z', | ||
'end_date' : '2019-07-26T00:00:00Z', | ||
'insights_buffer_days': '10' # set attribution window other than 1, 7 or 28 | ||
} | ||
if original: | ||
return return_value | ||
|
||
return_value["start_date"] = self.start_date | ||
return return_value | ||
|
||
def test_run(self): | ||
""" | ||
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) | ||
# run check mode | ||
check_job_name = runner.run_check_mode(self, conn_id) | ||
# get exit status | ||
exit_status = menagerie.get_exit_status(conn_id, check_job_name) | ||
# get discovery error message | ||
discovery_error_message = exit_status.get('discovery_error_message') | ||
# validate the error message | ||
self.assertEquals(discovery_error_message, "The attribution window must be 1, 7 or 28.") |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import unittest | ||
import tap_facebook.__init__ as tap_facebook | ||
|
||
class TestAttributionWindow(unittest.TestCase): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's fine to leave in this unittest, but this should be a tap-tester case. We want to prove the error is thrown during discovery. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @kspeer825 Added integration test for verifying error is thrown in discovery mode. |
||
""" | ||
Test case to verify that proper error message is raise | ||
when user enters attribution window other than 1, 7 and 28 | ||
""" | ||
|
||
def test_invalid_attribution_window(self): | ||
error_message = None | ||
|
||
# set config | ||
tap_facebook.CONFIG = { | ||
"start_date": "2019-01-01T00:00:00Z", | ||
"account_id": "test_account_id", | ||
"access_token": "test_access_token", | ||
"insights_buffer_days": 30 | ||
} | ||
|
||
try: | ||
# initialize 'AdsInsights' stream as attribution window is only supported in those streams | ||
tap_facebook.AdsInsights("test", "test", "test", None, {}, {}) | ||
except Exception as e: | ||
# save error message for assertion | ||
error_message = str(e) | ||
|
||
# verify the error message was as expected | ||
self.assertEquals(error_message, "The attribution window must be 1, 7 or 28.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need this method here, isn't it defined in the base.py?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is defined, but here we wanted to use different values of attribution window.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then can't we add one more optional parameter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, here only 1 argument can be passed in the function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an unfortunate restriction of the tap-tester backend.