-
Notifications
You must be signed in to change notification settings - Fork 23
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
chore: refactor shared tests for modular testing #494
Conversation
Sample app builds 📱Below you will find the list of the latest versions of the sample apps. It's recommended to always download the latest builds of the sample apps to accurately test the pull request.
|
Make testing the singleton `instance` possible. | ||
Note: It's recommended to delete app data before doing this to prevent loading persisted credentials | ||
*/ | ||
static func resetSharedInstance() { |
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.
Moved this and the constructor to #if DEBUG
, assuming it isn't required by the customers
Common initialization method for setting up the shared `CustomerIO` instance. | ||
This method is intended to be used by both actual implementations and in tests, ensuring that tests closely mimic the real-world implementation. | ||
*/ | ||
private static func initialize(implementation: DataPipelineInstance, diGraph: DIGraph) { |
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.
Added this to make sure both tests and actual SDK is initialized using same path.
// Any implementation of the interface works for unit tests. | ||
|
||
@discardableResult | ||
static func setUpSharedInstanceForUnitTest(implementation: CustomerIOInstance, diGraph: DIGraph) -> CustomerIO { |
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.
All classes have now similar names, I tried to keep them descriptive for convenience.
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.
would we need DiGraphShared
here as well?
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.
and we should ideally not need DIGraph
at all here, since its not being replaced with DiGraphShared
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.
Added only DIGraph
here as CustomerIOInstance
only uses it in Common
yet. But I do agree, we do need to cleanup graphs. I'll create separate ticket for it.
/// or a specific module (e.g., `MessagingPush`). | ||
/// | ||
/// For SDK-wide tests, child classes can conveniently inherit from `UnitTest`, designed specifically for testing only SDK APIs. | ||
open class UnitTestBase<Component>: XCTestCase { |
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 very much similar to what we have today in SharedTests.UnitTest
, with only relocation and helping new changes
diGraph.override(value: deviceInfoStub, forType: DeviceInfo.self) | ||
} | ||
|
||
override open func initializeSDKComponents() -> CustomerIO? { |
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 how each module can setup SDK/module initialization the way they want
/// Base class for unit testing within the module, extending `UnitTestBase` with setup and utilities | ||
/// specific to module components. Ideal for isolated tests of individual functions and classes. | ||
open class UnitTest: SharedTests.UnitTestBase<CustomerIO> { | ||
public var dataPipelineConfigOptions: DataPipelineConfigOptions! |
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.
Every module can have their own config
// setup and override dependencies before creating SDK instance, as Shared graph may be initialized and used immediately | ||
setUpDependencies() | ||
// setup SDK instance and set necessary components for testing | ||
initializeSDKComponents() |
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.
Used open methods for setting up SDK/module so they can be overridden and implemented by child classes as needed
|
||
// function meant to only be in tests as deleting all files from a search path (where app files can be stored!) is | ||
// not a good idea. | ||
private func deleteAllFiles() { |
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.
Moved this from SharedTest
to Tracking
as I think it is only needed by Tracking
module now
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.
Would you mind breaking apart this pull request into smaller ones to facilitate the review process? The size of it is quite large, and it is taking some time to review.
I really appreciate the thorough breakdown of the changes in the pull request description. It seems that the breakdown could provide helpful guidance on how to divide the changes into smaller, more manageable pull requests.
Thank @levibostian for sharing the concern. I've moved this discussion to Slack so we can talk about it in more detail and resolve it more quickly. |
Package.swift
Outdated
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.
Should we also update Tracking
test target with this?
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.
Not really needed. Because tracking has already correct dependencies (i.e. DataPipeline
and SharedTests
). And unfortunately, test target of DataPipeline
cannot be added as dependency to Tracking
so they don't need to be updated.
// Any implementation of the interface works for unit tests. | ||
|
||
@discardableResult | ||
static func setUpSharedInstanceForUnitTest(implementation: CustomerIOInstance, diGraph: DIGraph) -> CustomerIO { |
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.
would we need DiGraphShared
here as well?
// Any implementation of the interface works for unit tests. | ||
|
||
@discardableResult | ||
static func setUpSharedInstanceForUnitTest(implementation: CustomerIOInstance, diGraph: DIGraph) -> CustomerIO { |
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.
and we should ideally not need DIGraph
at all here, since its not being replaced with DiGraphShared
// automatically add the AutoTrackingScreenViews plugin | ||
DataPipeline.shared.analytics.add(plugin: AutoTrackingScreenViews(filterAutoScreenViewEvents: sdkConfig.filterAutoScreenViewEvents, autoScreenViewBody: sdkConfig.autoScreenViewBody)) | ||
} | ||
initialize(implementation: implementation, diGraph: newDiGraph) |
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.
I am guessing there is not change is the code but rather just made a method for the same changes?
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, correct. No change in logic, only code moved to new initialize
so it can be reused by methods initializing the module for testing.
static func setUpSharedInstanceForIntegrationTest(diGraphShared: DIGraphShared, diGraph: DIGraph, autoAddCustomerIODestination: Bool) -> CustomerIOInstance { | ||
let sdkConfig = diGraph.sdkConfig | ||
var moduleConfig = DataPipelineConfigOptions.Factory.create(sdkConfig: sdkConfig) | ||
// allow overriding autoAddCustomerIODestination so http requests can be ignored during tests |
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.
I believe its because in tracking config we do not have any concept of this, let's add a comment explaining that if that's true
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.
Correct, updated
enableLogs: Bool = false, | ||
siteId: String? = nil, | ||
writeKey: String? = nil, | ||
modifySdkConfig: ((inout SdkConfig) -> Void)? = nil, |
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.
we should ideally be moving away from sdkConfig as well from test, maybe in next tickets.
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.
Agreed, I'll create ticket for it.
Sources/Tracking/CustomerIO.swift
Outdated
// Integration tests use the actual implementation. | ||
|
||
@discardableResult | ||
static func setUpSharedInstanceForIntegrationTest(diGraphShared: DIGraphShared, diGraph: DIGraph, autoAddCustomerIODestination: Bool) -> CustomerIOInstance { |
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.
autoAddCustomerIODestination
should probably have a default value?
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.
Updated
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.
Looks good 👍
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.
With Shahroz's approval and seeing the good conversation in the PR, I'll remove my request for change to help unblock this.
closes: MOB-51
Changes
UnitTestBase
to facilitate module-wise testing setupUnitTest
andIntegrationTest
classes inSharedTest
UnitTest
andIntegrationTest
classes inDataPipeline
,Tracking
,MessagingInApp
, andMessagingPush
to enable independent testing of each module