-
Notifications
You must be signed in to change notification settings - Fork 94
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
Move all fields test to new framework #239
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
60aa211
Move all fields test to new framework
bhuvana-talend bd451ee
As per PR review, removed the overrridden methods and moved some comm…
bhuvana-talend 16279de
Moved some fields to tap-tester base case
bhuvana-talend 8e118c9
Implemented PR Review comments
bhuvana-talend b279239
Improvements in new framework all fields test to incorporate the logi…
bhuvana-talend cb62f07
Removed not-used method and constants
bhuvana-talend 1026c65
Removed the extra fields for deals as it is covered in bad prefix
bhuvana-talend b9ef05e
Fixed removed_bad_keys to add to bad keys only if it is not in the ot…
bhuvana-talend fcd97dc
Merge branch 'master' into tdl-24438-2
bhuvana-talend de4bdb1
Merge branch 'master' into tdl-24438-2
bhuvana-talend 25ba332
Merge branch 'master' into tdl-24438-2
bhuvana-talend e57af17
Removed unneeded line
bhuvana-talend File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
import os | ||
import unittest | ||
from datetime import datetime as dt | ||
from datetime import timedelta | ||
|
||
import tap_tester.menagerie as menagerie | ||
import tap_tester.connections as connections | ||
import tap_tester.runner as runner | ||
from tap_tester.base_suite_tests.base_case import BaseCase | ||
from tap_tester import LOGGER | ||
|
||
|
||
class HubspotBaseCase(BaseCase): | ||
|
||
# set the default start date which can be overridden in the tests. | ||
start_date = BaseCase.timedelta_formatted(dt.utcnow(), delta=timedelta(days=-1)) | ||
|
||
EXTRA_FIELDS = { | ||
"contacts": { "versionTimestamp" } | ||
} | ||
|
||
def setUp(self): | ||
missing_envs = [x for x in [ | ||
'TAP_HUBSPOT_REDIRECT_URI', | ||
'TAP_HUBSPOT_CLIENT_ID', | ||
'TAP_HUBSPOT_CLIENT_SECRET', | ||
'TAP_HUBSPOT_REFRESH_TOKEN' | ||
] if os.getenv(x) is None] | ||
if missing_envs: | ||
raise Exception("Missing environment variables: {}".format(missing_envs)) | ||
|
||
@staticmethod | ||
def get_type(): | ||
return "platform.hubspot" | ||
|
||
@staticmethod | ||
def tap_name(): | ||
return "tap-hubspot" | ||
|
||
def get_properties(self): | ||
return {'start_date': self.start_date} | ||
|
||
def get_credentials(self): | ||
return {'refresh_token': os.getenv('TAP_HUBSPOT_REFRESH_TOKEN'), | ||
'client_secret': os.getenv('TAP_HUBSPOT_CLIENT_SECRET'), | ||
'redirect_uri': os.getenv('TAP_HUBSPOT_REDIRECT_URI'), | ||
'client_id': os.getenv('TAP_HUBSPOT_CLIENT_ID')} | ||
|
||
@classmethod | ||
def expected_metadata(cls): # DOCS_BUG https://stitchdata.atlassian.net/browse/DOC-1523) | ||
"""The expected streams and metadata about the streams""" | ||
|
||
return { | ||
"campaigns": { | ||
BaseCase.PRIMARY_KEYS: {"id"}, | ||
BaseCase.REPLICATION_METHOD: BaseCase.FULL_TABLE, | ||
BaseCase.OBEYS_START_DATE: False | ||
}, | ||
"companies": { | ||
BaseCase.PRIMARY_KEYS: {"companyId"}, | ||
BaseCase.REPLICATION_METHOD: BaseCase.INCREMENTAL, | ||
BaseCase.REPLICATION_KEYS: {"property_hs_lastmodifieddate"}, | ||
BaseCase.API_LIMIT: 250, | ||
BaseCase.OBEYS_START_DATE: True | ||
}, | ||
"contact_lists": { | ||
BaseCase.PRIMARY_KEYS: {"listId"}, | ||
BaseCase.REPLICATION_METHOD: BaseCase.INCREMENTAL, | ||
BaseCase.REPLICATION_KEYS: {"updatedAt"}, | ||
BaseCase.API_LIMIT: 250, | ||
BaseCase.OBEYS_START_DATE: True | ||
}, | ||
"contacts": { | ||
BaseCase.PRIMARY_KEYS: {"vid"}, | ||
BaseCase.REPLICATION_METHOD: BaseCase.INCREMENTAL, | ||
BaseCase.REPLICATION_KEYS: {"versionTimestamp"}, | ||
BaseCase.API_LIMIT: 100, | ||
BaseCase.OBEYS_START_DATE: True | ||
}, | ||
"contacts_by_company": { | ||
BaseCase.PRIMARY_KEYS: {"company-id", "contact-id"}, | ||
BaseCase.REPLICATION_METHOD: BaseCase.INCREMENTAL, | ||
BaseCase.API_LIMIT: 100, | ||
BaseCase.OBEYS_START_DATE: True, | ||
BaseCase.PARENT_STREAM: 'companies' | ||
}, | ||
"deal_pipelines": { | ||
BaseCase.PRIMARY_KEYS: {"pipelineId"}, | ||
BaseCase.REPLICATION_METHOD: BaseCase.FULL_TABLE, | ||
BaseCase.OBEYS_START_DATE: False, | ||
}, | ||
"deals": { | ||
BaseCase.PRIMARY_KEYS: {"dealId"}, | ||
BaseCase.REPLICATION_METHOD: BaseCase.INCREMENTAL, | ||
BaseCase.REPLICATION_KEYS: {"property_hs_lastmodifieddate"}, | ||
BaseCase.OBEYS_START_DATE: True | ||
}, | ||
"email_events": { | ||
BaseCase.PRIMARY_KEYS: {"id"}, | ||
BaseCase.REPLICATION_METHOD: BaseCase.INCREMENTAL, | ||
BaseCase.REPLICATION_KEYS: {"startTimestamp"}, | ||
BaseCase.API_LIMIT: 1000, | ||
BaseCase.OBEYS_START_DATE: True | ||
}, | ||
"engagements": { | ||
BaseCase.PRIMARY_KEYS: {"engagement_id"}, | ||
BaseCase.REPLICATION_METHOD: BaseCase.INCREMENTAL, | ||
BaseCase.REPLICATION_KEYS: {"lastUpdated"}, | ||
BaseCase.API_LIMIT: 250, | ||
BaseCase.OBEYS_START_DATE: True | ||
}, | ||
"forms": { | ||
BaseCase.PRIMARY_KEYS: {"guid"}, | ||
BaseCase.REPLICATION_METHOD: BaseCase.INCREMENTAL, | ||
BaseCase.REPLICATION_KEYS: {"updatedAt"}, | ||
BaseCase.OBEYS_START_DATE: True | ||
}, | ||
"owners": { | ||
BaseCase.PRIMARY_KEYS: {"ownerId"}, | ||
BaseCase.REPLICATION_METHOD: BaseCase.INCREMENTAL, | ||
BaseCase.REPLICATION_KEYS: {"updatedAt"}, | ||
BaseCase.OBEYS_START_DATE: True # TODO is this a BUG? | ||
}, | ||
"subscription_changes": { | ||
BaseCase.PRIMARY_KEYS: {"timestamp", "portalId", "recipient"}, | ||
BaseCase.REPLICATION_METHOD: BaseCase.INCREMENTAL, | ||
BaseCase.REPLICATION_KEYS: {"startTimestamp"}, | ||
BaseCase.API_LIMIT: 1000, | ||
BaseCase.OBEYS_START_DATE: True | ||
}, | ||
"workflows": { | ||
BaseCase.PRIMARY_KEYS: {"id"}, | ||
BaseCase.REPLICATION_METHOD: BaseCase.INCREMENTAL, | ||
BaseCase.REPLICATION_KEYS: {"updatedAt"}, | ||
BaseCase.OBEYS_START_DATE: True | ||
}, | ||
"tickets": { | ||
BaseCase.PRIMARY_KEYS: {"id"}, | ||
BaseCase.REPLICATION_METHOD: BaseCase.INCREMENTAL, | ||
BaseCase.REPLICATION_KEYS: {"updatedAt"}, | ||
BaseCase.API_LIMIT: 100, | ||
BaseCase.OBEYS_START_DATE: True | ||
} | ||
} |
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,112 @@ | ||
import unittest | ||
from tap_tester.base_suite_tests.all_fields_test import AllFieldsTest | ||
from tap_tester.logger import LOGGER | ||
from base_hubspot import HubspotBaseCase | ||
from client import TestClient | ||
|
||
class HubspotAllFieldsTest(AllFieldsTest, HubspotBaseCase): | ||
"""Hubspot all fields test implementation """ | ||
EXTRA_FIELDS = HubspotBaseCase.EXTRA_FIELDS | ||
|
||
@staticmethod | ||
def name(): | ||
return "tt_hubspot_all_fields" | ||
|
||
def streams_to_test(self): | ||
"""expected streams minus the streams not under test""" | ||
return self.expected_stream_names().difference({ | ||
'owners', | ||
'subscription_changes', # BUG_TDL-14938 https://jira.talendforge.org/browse/TDL-14938 | ||
}) | ||
|
||
def setUp(self): | ||
self.maxDiff = None # see all output in failure | ||
|
||
test_client = TestClient(start_date=self.get_properties()['start_date']) | ||
|
||
self.expected_records = dict() | ||
streams = self.streams_to_test() | ||
stream_to_run_last = 'contacts_by_company' | ||
if stream_to_run_last in streams: | ||
streams.remove(stream_to_run_last) | ||
streams = list(streams) | ||
streams.append(stream_to_run_last) | ||
|
||
for stream in streams: | ||
# Get all records | ||
if stream == 'contacts_by_company': | ||
company_ids = [company['companyId'] for company in self.expected_records['companies']] | ||
self.expected_records[stream] = test_client.read(stream, parent_ids=company_ids) | ||
else: | ||
self.expected_records[stream] = test_client.read(stream) | ||
|
||
for stream, records in self.expected_records.items(): | ||
LOGGER.info("The test client found %s %s records.", len(records), stream) | ||
|
||
super().setUp() | ||
self.convert_datatype(self.expected_records) | ||
|
||
def convert_datatype(self, expected_records): | ||
# Convert the time stamp data type, Get keys with data and with no data | ||
for stream, records in expected_records.items(): | ||
expected_keys = set() | ||
for record in records: | ||
|
||
expected_keys = expected_keys.union(record.keys()) | ||
# convert timestamps to string formatted datetime | ||
timestamp_keys = {'timestamp'} | ||
for key in timestamp_keys: | ||
timestamp = record.get(key) | ||
if timestamp: | ||
record[key]=self.datetime_from_timestamp(timestamp/1000, str_format=self.BASIC_DATE_FORMAT) | ||
|
||
self.KEYS_WITH_NO_DATA[stream] = self.selected_fields.get(stream).difference(expected_keys) | ||
|
||
return expected_records | ||
|
||
def remove_bad_keys(self, stream): | ||
# NB: The following woraround is for dynamic fields on the `deals` stream that we just can't track. | ||
# At the time of implementation there is no customer feedback indicating that these dynamic fields | ||
# would prove useful to an end user. The ones that we replicated with the test client are specific | ||
# to our test data. We have determined that the filtering of these fields is an expected behavior. | ||
# deals workaround for 'property_hs_date_entered_<property>' fields | ||
# BUG_TDL-14993 | https://jira.talendforge.org/browse/TDL-14993 | ||
# Has an value of object with key 'value' and value 'Null' | ||
if stream == 'deals': | ||
bad_key_prefixes = {'property_hs_date_entered_', 'property_hs_date_exited_', 'property_hs_time_in'} | ||
bad_keys = set() | ||
for key in self.expected_all_keys: | ||
for bad_prefix in bad_key_prefixes: | ||
if key.startswith(bad_prefix) and key not in self.fields_replicated: | ||
bad_keys.add(key) | ||
for key in self.fields_replicated: | ||
for bad_prefix in bad_key_prefixes: | ||
if key.startswith(bad_prefix) and key not in self.expected_all_keys: | ||
bad_keys.add(key) | ||
|
||
for key in bad_keys: | ||
if key in self.expected_all_keys: | ||
self.expected_all_keys.remove(key) | ||
elif key in self.fields_replicated: | ||
self.fields_replicated.remove(key) | ||
|
||
########################################################################## | ||
# Tests To Skip | ||
########################################################################## | ||
|
||
@unittest.skip("Skip till all cards of missing fields are fixed. TDL-16145 ") | ||
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. This would be nice place to use the tap-tester @skipUntilDone to ensure this gets picked up as soon as TDL-16145 is completed. |
||
def test_values_of_all_fields(self): | ||
for stream in self.test_streams: | ||
with self.subTest(stream=stream): | ||
|
||
# gather expectations | ||
expected_all_keys = self.selected_fields.get(stream, set()) - set(self.MISSING_FIELDS.get(stream, {})) | ||
|
||
# gather results | ||
fields_replicated = self.actual_fields.get(stream, set()) | ||
|
||
# verify that all fields are sent to the target | ||
# test the combination of all records | ||
self.assertSetEqual(fields_replicated, expected_all_keys, | ||
logging=f"verify all fields are replicated for stream {stream}") | ||
|
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
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Love the fact that you just have the differences in the setup that are unique to this tap and then call the existing setup so it is easy to see why we are overriding this method.