-
Notifications
You must be signed in to change notification settings - Fork 8
add unittests and integrationt tests #39
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
base: master
Are you sure you want to change the base?
Changes from all commits
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,115 @@ | ||
| import os | ||
|
|
||
| from tap_tester import menagerie | ||
| from tap_tester.base_suite_tests.base_case import BaseCase | ||
|
|
||
|
|
||
| STREAMS = [ | ||
| "accounts_table", | ||
| "channels_table", | ||
| "inboxes_table", | ||
| "tags_table", | ||
| "teammates_table", | ||
| "teams_table", | ||
| ] | ||
|
|
||
| INCREMENTAL_STREAMS = set(STREAMS) # all streams are INCREMENTAL | ||
|
|
||
| FULL_TABLE_STREAMS = set() | ||
|
|
||
| PRIMARY_KEYS = ["analytics_date", "analytics_range", "report_id", "metric_id"] | ||
|
|
||
|
|
||
| class FrontAppBaseTest(BaseCase): | ||
| """Setup expectations for test sub classes. | ||
|
|
||
| Metadata describing streams. A bunch of shared methods that are used | ||
| in tap-tester tests. Shared tap-specific methods (as needed). | ||
| """ | ||
|
|
||
| start_date = "2019-01-01T00:00:00Z" | ||
|
|
||
| @staticmethod | ||
| def tap_name(): | ||
| """The name of the tap.""" | ||
| return "tap-frontapp" | ||
|
|
||
| @staticmethod | ||
| def get_type(): | ||
| """The Stitch connection type slug.""" | ||
| return "platform.frontapp" | ||
|
|
||
| def setUp(self): | ||
| """Fail fast if required credentials env vars are missing.""" | ||
| missing = [v for v in ["TAP_FRONTAPP_TOKEN"] if not os.getenv(v)] | ||
| if missing: | ||
| raise Exception(f"Missing required environment variables: {missing}") | ||
|
|
||
| def get_properties(self, original: bool = True): | ||
| """Configuration properties required for the tap.""" | ||
| return_value = { | ||
| "start_date": self.start_date, | ||
| } | ||
| if original: | ||
| return return_value | ||
|
|
||
| return_value["start_date"] = self.start_date | ||
| return return_value | ||
|
|
||
| @staticmethod | ||
| def get_credentials(): | ||
| """Authentication information for the test account. | ||
| Values are read from environment variables — never hardcode credentials. | ||
| """ | ||
| return { | ||
| "token": os.getenv("TAP_FRONTAPP_TOKEN"), | ||
| } | ||
|
|
||
| @classmethod | ||
| def expected_metadata(cls): | ||
| """The expected streams and metadata about the streams.""" | ||
| pk_set = set(PRIMARY_KEYS) | ||
| return { | ||
| "accounts_table": { | ||
| cls.PRIMARY_KEYS: pk_set, | ||
| cls.REPLICATION_METHOD: cls.INCREMENTAL, | ||
| cls.REPLICATION_KEYS: {"analytics_date"}, | ||
| cls.OBEYS_START_DATE: True, | ||
| cls.API_LIMIT: 1, | ||
| }, | ||
| "channels_table": { | ||
| cls.PRIMARY_KEYS: pk_set, | ||
| cls.REPLICATION_METHOD: cls.INCREMENTAL, | ||
| cls.REPLICATION_KEYS: {"analytics_date"}, | ||
| cls.OBEYS_START_DATE: True, | ||
| cls.API_LIMIT: 1, | ||
| }, | ||
| "inboxes_table": { | ||
| cls.PRIMARY_KEYS: pk_set, | ||
| cls.REPLICATION_METHOD: cls.INCREMENTAL, | ||
| cls.REPLICATION_KEYS: {"analytics_date"}, | ||
| cls.OBEYS_START_DATE: True, | ||
| cls.API_LIMIT: 1, | ||
| }, | ||
| "tags_table": { | ||
| cls.PRIMARY_KEYS: pk_set, | ||
| cls.REPLICATION_METHOD: cls.INCREMENTAL, | ||
| cls.REPLICATION_KEYS: {"analytics_date"}, | ||
| cls.OBEYS_START_DATE: True, | ||
| cls.API_LIMIT: 1, | ||
| }, | ||
| "teammates_table": { | ||
| cls.PRIMARY_KEYS: pk_set, | ||
| cls.REPLICATION_METHOD: cls.INCREMENTAL, | ||
| cls.REPLICATION_KEYS: {"analytics_date"}, | ||
| cls.OBEYS_START_DATE: True, | ||
| cls.API_LIMIT: 1, | ||
| }, | ||
| "teams_table": { | ||
| cls.PRIMARY_KEYS: pk_set, | ||
| cls.REPLICATION_METHOD: cls.INCREMENTAL, | ||
| cls.REPLICATION_KEYS: {"analytics_date"}, | ||
| cls.OBEYS_START_DATE: True, | ||
| cls.API_LIMIT: 1, | ||
| }, | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| """Test that all schema fields are replicated.""" | ||
| from base import FrontAppBaseTest | ||
| from tap_tester.base_suite_tests.all_fields_test import AllFieldsTest | ||
|
|
||
| # Fields that exist in the schema but may not be returned by the FrontApp API | ||
| # in all test environments. Populate after a first real test run if needed. | ||
| KNOWN_MISSING_FIELDS = { | ||
| # "<stream_name>": {"<field_name>"}, | ||
| } | ||
|
|
||
|
|
||
| class FrontAppAllFields(AllFieldsTest, FrontAppBaseTest): | ||
| """Ensure running the tap with all streams and fields selected results in | ||
| the replication of all fields.""" | ||
|
|
||
| MISSING_FIELDS = KNOWN_MISSING_FIELDS | ||
|
|
||
| @staticmethod | ||
| def name(): | ||
| return "tap_tester_frontapp_all_fields_test" | ||
|
|
||
| def streams_to_test(self): | ||
| # Exclude streams with no test data or no API access in the test environment | ||
| streams_to_exclude = set() | ||
| return self.expected_stream_names().difference(streams_to_exclude) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| """Test that with no fields selected, automatic fields are still replicated.""" | ||
| from base import FrontAppBaseTest | ||
| from tap_tester.base_suite_tests.automatic_fields_test import MinimumSelectionTest | ||
|
|
||
|
|
||
| class FrontAppAutomaticFields(MinimumSelectionTest, FrontAppBaseTest): | ||
| """Test that with no fields selected for a stream, automatic (primary key and | ||
| replication key) fields are still replicated.""" | ||
|
|
||
| @staticmethod | ||
| def name(): | ||
| return "tap_tester_frontapp_automatic_fields_test" | ||
|
|
||
| def streams_to_test(self): | ||
| # Exclude streams with known missing test data | ||
| streams_to_exclude = set() | ||
| return self.expected_stream_names().difference(streams_to_exclude) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| """Test tap sets a bookmark and respects it in subsequent runs.""" | ||
| from base import FrontAppBaseTest, FULL_TABLE_STREAMS | ||
| from tap_tester.base_suite_tests.bookmark_test import BookmarkTest | ||
|
|
||
|
|
||
| class FrontAppBookMarkTest(BookmarkTest, FrontAppBaseTest): | ||
| """Test tap sets a bookmark and respects it for the next sync of a stream.""" | ||
|
|
||
| bookmark_format = "%Y-%m-%dT%H:%M:%SZ" | ||
| initial_bookmarks = { | ||
| "bookmarks": { | ||
| "accounts_table": {"date_to_resume": "2020-01-01 00:00:00"}, | ||
| "channels_table": {"date_to_resume": "2020-01-01 00:00:00"}, | ||
| "inboxes_table": {"date_to_resume": "2020-01-01 00:00:00"}, | ||
| "tags_table": {"date_to_resume": "2020-01-01 00:00:00"}, | ||
| "teammates_table": {"date_to_resume": "2020-01-01 00:00:00"}, | ||
| "teams_table": {"date_to_resume": "2020-01-01 00:00:00"}, | ||
| } | ||
|
Comment on lines
+9
to
+18
|
||
| } | ||
|
|
||
| @staticmethod | ||
| def name(): | ||
| return "tap_tester_frontapp_bookmark_test" | ||
|
|
||
| def streams_to_test(self): | ||
| # Exclude any FULL_TABLE streams (none currently) | ||
| streams_to_exclude = FULL_TABLE_STREAMS | ||
| return self.expected_stream_names().difference(streams_to_exclude) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| """Test tap discovery mode and metadata.""" | ||
| from base import FrontAppBaseTest | ||
| from tap_tester.base_suite_tests.discovery_test import DiscoveryTest | ||
|
|
||
|
|
||
| class FrontAppDiscoveryTest(DiscoveryTest, FrontAppBaseTest): | ||
| """Test tap discovery mode and metadata conforms to standards.""" | ||
|
|
||
| @staticmethod | ||
| def name(): | ||
| return "tap_tester_frontapp_discovery_test" | ||
|
|
||
| def streams_to_test(self): | ||
| return self.expected_stream_names() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| """Test that interrupted sync resumes correctly from the saved bookmark.""" | ||
| from base import FrontAppBaseTest, FULL_TABLE_STREAMS | ||
| from tap_tester.base_suite_tests.interrupted_sync_tests import InterruptedSyncTest | ||
|
|
||
|
|
||
| class FrontAppInterruptedSyncTest(InterruptedSyncTest, FrontAppBaseTest): | ||
| """Test that if a sync is interrupted, the next sync resumes from the correct bookmark.""" | ||
|
|
||
| @staticmethod | ||
| def name(): | ||
| return "tap_tester_frontapp_interrupted_sync_test" | ||
|
|
||
| def streams_to_test(self): | ||
| # Only test INCREMENTAL streams (FULL_TABLE re-syncs fully anyway) | ||
| streams_to_exclude = FULL_TABLE_STREAMS | ||
| return self.expected_stream_names().difference(streams_to_exclude) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| """Test that the tap can replicate multiple pages of data.""" | ||
| from base import FrontAppBaseTest | ||
| from tap_tester.base_suite_tests.pagination_test import PaginationTest | ||
|
|
||
|
|
||
| class FrontAppPaginationTest(PaginationTest, FrontAppBaseTest): | ||
| """Ensure tap can replicate multiple pages of data for streams that use pagination.""" | ||
|
|
||
| @staticmethod | ||
| def name(): | ||
| return "tap_tester_frontapp_pagination_test" | ||
|
|
||
| def streams_to_test(self): | ||
| # FrontApp analytics streams return one daily report per entity. | ||
| # Most test environments do not have enough entities to exceed one page. | ||
| # Exclude all streams until a test environment with sufficient data is available. | ||
| streams_to_exclude = { | ||
| "accounts_table", # sandbox typically has < API_LIMIT entities | ||
| "channels_table", | ||
| "inboxes_table", | ||
| "tags_table", | ||
| "teammates_table", | ||
| "teams_table", | ||
| } | ||
| return self.expected_stream_names().difference(streams_to_exclude) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| """Test that data is replicated from the configured start_date.""" | ||
| from base import FrontAppBaseTest, FULL_TABLE_STREAMS | ||
| from tap_tester.base_suite_tests.start_date_test import StartDateTest | ||
|
|
||
|
|
||
| class FrontAppStartDateTest(StartDateTest, FrontAppBaseTest): | ||
| """Instantiate start date according to the desired data set and run the test.""" | ||
|
|
||
| @staticmethod | ||
| def name(): | ||
| return "tap_tester_frontapp_start_date_test" | ||
|
|
||
| def streams_to_test(self): | ||
| # Exclude FULL_TABLE streams (none currently) and streams with insufficient test data | ||
| streams_to_exclude = FULL_TABLE_STREAMS | ||
| return self.expected_stream_names().difference(streams_to_exclude) | ||
|
|
||
| @property | ||
| def start_date_1(self): | ||
| return "2019-01-01T00:00:00Z" | ||
|
|
||
| @property | ||
| def start_date_2(self): | ||
| return "2020-01-01T00:00:00Z" |
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.
Class name
FrontAppBookMarkTesthas inconsistent capitalization ("BookMark") compared to the other test classes in this suite (e.g.,FrontAppStartDateTest,FrontAppPaginationTest). Consider renaming toFrontAppBookmarkTestfor consistency and easier discovery/searching.