forked from AutoIDM/tap-googleads
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add conversion window test * add conversion window test * wip updated tests to worka with currently syncing dev branch [skip ci] * Revert removal of metric compatibility removal (AutoIDM#29) * Revert removal of metric compatibility removal * Whitespace cleanup * Add currently syncing (AutoIDM#24) * Sync all customers for a given stream * Add logging to see when we retry requests * Update currently_syncing with customerId too. Write state as soon as we update it * Add the customerId to the bookmark keys * Add shuffle for customerId and tap_stream_id; add shuffle unit tests * Bug fix for when currently_syncing is null * Fix exception handling typeError * Fix none cases for currently_syncing * Fix currently_syncing to write a tuple we can read in later * Add get_customer_ids so we can use it in the tests * Fix manipulated_state to account for customer_ids * Update assertion for currently_syncing * Fix currently syncing assertion * Move bookmark access into Full Table assertions section Full Table doesn't need the "stream_name and customer id" key logic * Remove duplicate assertion * Revert 6db016e7ec29c2b00973b671c1efdf9451aca9c2 * Update bookmark to read stream->customer->replication_key * Update tap to write bookmarks as stream->customer->replication_key * Update manipulated state to nest stream->customer->replication_key * Run bookmark assertions for every customer * Fix dict comprehension typo * Fix conflict with main * Remove `get_state_key` again, use env var instead of hardcoded value * Add missing dependency * Move currently-syncing-null-out to the end of sync to prevent gaps * Sort selected_streams and customers to guarantee consistency across runs * Don't let the tap write (None, None) * Sort selected_streams and customers effectively * Update currently_syncing test assertions * Add sort functions for streams and customers * Update `shuffle` to handle a missing value * Update unit tests to use sort_function, add a test for shuffling streams * Add end date (AutoIDM#28) * Add optional end date, add unit tests Co-authored-by: Andy Lu <[email protected]> * Test functions can't be named run_test apparently * Rename do_thing * Extract `get_queries_from_sync` as a function * Remove unused variable * Refactor tests to be more explicit * Mock singer.utils.now to return a specific date Co-authored-by: Andy Lu <[email protected]> * add conversion_window test * fixed conversion window unittests, bug removed Co-authored-by: dylan-stitch <[email protected]> Co-authored-by: Andy Lu <[email protected]> Co-authored-by: kspeer <[email protected]> * Bump to v0.2.0, update changelog (AutoIDM#31) * Bump to v0.2.0, update changelog * Add link for this PR, fix link syntax * Update changelog format * expanded conversion window testing for error case, BUG linked * parallelism 8 -> 12 * added unittest for start date within conversion window Co-authored-by: kspeer <[email protected]> Co-authored-by: Dylan <[email protected]> Co-authored-by: dylan-stitch <[email protected]> Co-authored-by: Andy Lu <[email protected]>
- Loading branch information
1 parent
8ce42be
commit 5b032dd
Showing
4 changed files
with
350 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
"""Test tap configurable properties. Specifically the conversion_window""" | ||
import os | ||
from datetime import datetime as dt | ||
from datetime import timedelta | ||
|
||
from tap_tester import menagerie, connections, runner | ||
|
||
from base import GoogleAdsBase | ||
|
||
|
||
class ConversionWindowBaseTest(GoogleAdsBase): | ||
""" | ||
Test tap's sync mode can execute with valid conversion_window values set. | ||
Validate setting the conversion_window configurable property. | ||
Test Cases: | ||
Verify tap throws critical error when a value is provided directly by a user which is | ||
outside the set of acceptable values. | ||
Verify connection can be created, and tap can discover and sync with a conversion window | ||
set to the following values | ||
Acceptable values: { 1 through 30, 60, 90} | ||
""" | ||
conversion_window = '' | ||
|
||
def name(self): | ||
return f"tt_google_ads_conv_window_{self.conversion_window}" | ||
|
||
def get_properties(self): | ||
"""Configurable properties, with a switch to override the 'start_date' property""" | ||
return { | ||
'start_date': dt.strftime(dt.utcnow() - timedelta(days=91), self.START_DATE_FORMAT), | ||
'user_id': 'not used?', # TODO ? | ||
'customer_ids': ','.join(self.get_customer_ids()), | ||
'conversion_window': self.conversion_window, | ||
'login_customer_ids': [{"customerId": os.getenv('TAP_GOOGLE_ADS_CUSTOMER_ID'), | ||
"loginCustomerId": os.getenv('TAP_GOOGLE_ADS_LOGIN_CUSTOMER_ID'),}], | ||
} | ||
|
||
def run_test(self): | ||
""" | ||
Testing that basic sync functions without Critical Errors when | ||
a valid conversion_windown is set. | ||
""" | ||
print("Configurable Properties Test (conversion_window)") | ||
|
||
streams_to_test = { | ||
'campagins', | ||
'account_performance_report', | ||
} | ||
|
||
# Create a connection | ||
conn_id = connections.ensure_connection(self) | ||
|
||
# Run a discovery job | ||
found_catalogs = self.run_and_verify_check_mode(conn_id) | ||
|
||
# Perform table and field selection... | ||
core_catalogs = [catalog for catalog in found_catalogs | ||
if not self.is_report(catalog['stream_name']) | ||
and catalog['stream_name'] in streams_to_test] | ||
report_catalogs = [catalog for catalog in found_catalogs | ||
if self.is_report(catalog['stream_name']) | ||
and catalog['stream_name'] in streams_to_test] | ||
# select all fields for core streams and... | ||
self.select_all_streams_and_fields(conn_id, core_catalogs, select_all_fields=True) | ||
# select 'default' fields for report streams | ||
self.select_all_streams_and_default_fields(conn_id, report_catalogs) | ||
|
||
# set state to ensure conversion window is used | ||
today_datetime = dt.strftime(dt.utcnow(), self.REPLICATION_KEY_FORMAT) | ||
customer_id = os.getenv('TAP_GOOGLE_ADS_CUSTOMER_ID') | ||
initial_state = { | ||
'bookmarks': {stream: {customer_id: {'date': today_datetime}} | ||
for stream in streams_to_test | ||
if self.is_report(stream)} | ||
} | ||
menagerie.set_state(conn_id, initial_state) | ||
|
||
# Run a sync | ||
sync_job_name = runner.run_sync_mode(self, conn_id) | ||
|
||
# Verify the tap and target do not throw a critical error | ||
exit_status = menagerie.get_exit_status(conn_id, sync_job_name) | ||
menagerie.verify_sync_exit_status(self, exit_status, sync_job_name) | ||
|
||
# Verify tap replicates through today by check state | ||
final_state = menagerie.get_state(conn_id) | ||
self.assertDictEqual(final_state, initial_state) | ||
|
||
|
||
class ConversionWindowTestOne(ConversionWindowBaseTest): | ||
|
||
conversion_window = '1' | ||
|
||
def test_run(self): | ||
self.run_test() | ||
|
||
class ConversionWindowTestThirty(ConversionWindowBaseTest): | ||
|
||
conversion_window = '30' | ||
|
||
def test_run(self): | ||
self.run_test() | ||
|
||
class ConversionWindowTestSixty(ConversionWindowBaseTest): | ||
|
||
conversion_window = '60' | ||
|
||
def test_run(self): | ||
self.run_test() | ||
|
||
class ConversionWindowTestNinety(ConversionWindowBaseTest): | ||
|
||
conversion_window = '90' | ||
|
||
def test_run(self): | ||
self.run_test() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
"""Test tap configurable properties. Specifically the conversion_window""" | ||
import os | ||
import unittest | ||
from datetime import datetime as dt | ||
from datetime import timedelta | ||
|
||
from tap_tester import menagerie, connections, runner | ||
|
||
from base import GoogleAdsBase | ||
|
||
|
||
class ConversionWindowInvalidTest(GoogleAdsBase): | ||
""" | ||
Test tap's sync mode can execute with valid conversion_window values set. | ||
Validate setting the conversion_window configurable property. | ||
Test Cases: | ||
Verify tap throws critical error when a value is provided directly by a user which is | ||
outside the set of acceptable values. | ||
Verify connection can be created, and tap can discover and sync with a conversion window | ||
set to the following values | ||
Acceptable values: { 1 through 30, 60, 90} | ||
""" | ||
conversion_window = '' | ||
|
||
def name(self): | ||
return f"tt_googleads_conversion_invalid_{self.conversion_window}" | ||
|
||
def get_properties(self): | ||
"""Configurable properties, with a switch to override the 'start_date' property""" | ||
return { | ||
'start_date': dt.strftime(dt.utcnow() - timedelta(days=91), self.START_DATE_FORMAT), | ||
'user_id': 'not used?', # TODO ? | ||
'customer_ids': ','.join(self.get_customer_ids()), | ||
'conversion_window': self.conversion_window, | ||
'login_customer_ids': [{"customerId": os.getenv('TAP_GOOGLE_ADS_CUSTOMER_ID'), | ||
"loginCustomerId": os.getenv('TAP_GOOGLE_ADS_LOGIN_CUSTOMER_ID'),}], | ||
} | ||
|
||
def run_test(self): | ||
""" | ||
Testing that basic sync functions without Critical Errors when | ||
a valid conversion_windown is set. | ||
""" | ||
print("Configurable Properties Test (conversion_window)") | ||
|
||
streams_to_test = { | ||
'campagins', | ||
'account_performance_report', | ||
} | ||
|
||
try: | ||
# Create a connection | ||
conn_id = connections.ensure_connection(self) | ||
|
||
with self.subTest(): | ||
raise AssertionError(f"Conenction should not have been created with conversion_window: " | ||
f"value {self.conversion_window}, type {type(self.conversion_window)}") | ||
|
||
# Run a discovery job | ||
found_catalogs = self.run_and_verify_check_mode(conn_id) | ||
|
||
# Perform table and field selection... | ||
core_catalogs = [catalog for catalog in found_catalogs | ||
if not self.is_report(catalog['stream_name']) | ||
and catalog['stream_name'] in streams_to_test] | ||
report_catalogs = [catalog for catalog in found_catalogs | ||
if self.is_report(catalog['stream_name']) | ||
and catalog['stream_name'] in streams_to_test] | ||
# select all fields for core streams and... | ||
self.select_all_streams_and_fields(conn_id, core_catalogs, select_all_fields=True) | ||
# select 'default' fields for report streams | ||
self.select_all_streams_and_default_fields(conn_id, report_catalogs) | ||
|
||
# set state to ensure conversion window is used | ||
today_datetime = dt.strftime(dt.utcnow(), self.REPLICATION_KEY_FORMAT) | ||
customer_id = os.getenv('TAP_GOOGLE_ADS_CUSTOMER_ID') | ||
initial_state = { | ||
'bookmarks': {stream: {customer_id: {'date': today_datetime}} | ||
for stream in streams_to_test | ||
if self.is_report(stream)} | ||
} | ||
menagerie.set_state(conn_id, initial_state) | ||
|
||
# Run a sync | ||
sync_job_name = runner.run_sync_mode(self, conn_id) | ||
|
||
# Verify the tap and target throw a critical error | ||
exit_status = menagerie.get_exit_status(conn_id, sync_job_name) | ||
menagerie.verify_sync_exit_status(self, exit_status, sync_job_name) | ||
|
||
# Verify tap replicates through today by check state | ||
final_state = menagerie.get_state(conn_id) | ||
self.assertDictEqual(final_state, initial_state) | ||
|
||
with self.subTest(): | ||
raise AssertionError("Tap should not have ran sync with conversion_window: " | ||
f"value {self.conversion_window}, type {type(self.conversion_window)}") | ||
|
||
except Exception as ex: | ||
err_msg_1 = "'message': 'properties do not match schema'" | ||
err_msg_2 = "'bad_properties': ['conversion_window']" | ||
|
||
print("Expected exception occurred.") | ||
|
||
# Verify connection cannot be made with invalid conversion_window | ||
print(f"Validating error message contains {err_msg_1}") | ||
self.assertIn(err_msg_1, ex.args[0]) | ||
print(f"Validating error message contains {err_msg_2}") | ||
self.assertIn(err_msg_2, ex.args[0]) | ||
|
||
|
||
class ConversionWindowTestZeroInteger(ConversionWindowInvalidTest): | ||
|
||
conversion_window = 0 | ||
|
||
@unittest.skip("https://jira.talendforge.org/browse/TDL-18168" | ||
"[tap-google-ads] Invalid conversion_window values can be set when running tap directly") | ||
def test_run(self): | ||
self.run_test() | ||
|
||
|
||
class ConversionWindowTestZeroString(ConversionWindowInvalidTest): | ||
|
||
conversion_window = '0' | ||
|
||
def test_run(self): | ||
self.run_test() |
Oops, something went wrong.