Skip to content
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

Merged
merged 26 commits into from
Feb 6, 2024

Conversation

mrehan27
Copy link
Contributor

@mrehan27 mrehan27 commented Feb 1, 2024

closes: MOB-51

Changes

  • Updated test dependencies to align with actual dependencies for consistency
  • Introduced UnitTestBase to facilitate module-wise testing setup
  • Refactored UnitTest and IntegrationTest classes in SharedTest
  • Implemented base UnitTest and IntegrationTest classes in DataPipeline, Tracking, MessagingInApp, and MessagingPush to enable independent testing of each module
  • Streamlined and relocated utility methods for testing to enhance consistency
  • Updated documentation

@mrehan27 mrehan27 self-assigned this Feb 1, 2024
Copy link

github-actions bot commented Feb 1, 2024

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.


  • CocoaPods-FCM: Build failed. See CI job logs to determine the issue and try re-building.
  • APN-UIKit: mob-51 (1707142605)

Copy link

github-actions bot commented Feb 1, 2024

Warnings
⚠️

Swift Package Manager files (Package.) were modified but Cocoapods files (.podspec) files were not. This is error-prone when updating dependencies in one service but not the other. Double-check that you updated all of the correct files.

Generated by 🚫 dangerJS against 7ea5628

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() {
Copy link
Contributor Author

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) {
Copy link
Contributor Author

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 {
Copy link
Contributor Author

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.

Copy link
Contributor

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?

Copy link
Contributor

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

Copy link
Contributor Author

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 {
Copy link
Contributor Author

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

@mrehan27 mrehan27 marked this pull request as ready for review February 1, 2024 10:51
@mrehan27 mrehan27 requested a review from a team February 1, 2024 10:52
diGraph.override(value: deviceInfoStub, forType: DeviceInfo.self)
}

override open func initializeSDKComponents() -> CustomerIO? {
Copy link
Contributor Author

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!
Copy link
Contributor Author

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()
Copy link
Contributor Author

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() {
Copy link
Contributor Author

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

Copy link
Contributor

@levibostian levibostian left a 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.

@mrehan27
Copy link
Contributor Author

mrehan27 commented Feb 2, 2024

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
Copy link
Contributor

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?

Copy link
Contributor Author

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 {
Copy link
Contributor

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 {
Copy link
Contributor

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)
Copy link
Contributor

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?

Copy link
Contributor Author

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
Copy link
Contributor

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

Copy link
Contributor Author

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,
Copy link
Contributor

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.

Copy link
Contributor Author

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.

// Integration tests use the actual implementation.

@discardableResult
static func setUpSharedInstanceForIntegrationTest(diGraphShared: DIGraphShared, diGraph: DIGraph, autoAddCustomerIODestination: Bool) -> CustomerIOInstance {
Copy link
Contributor

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

Copy link
Contributor

@Shahroz16 Shahroz16 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good 👍

Copy link
Contributor

@levibostian levibostian left a 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.

@mrehan27 mrehan27 merged commit 2daa7b2 into main-replica-for-cdp Feb 6, 2024
4 of 7 checks passed
@mrehan27 mrehan27 deleted the mob-51 branch February 6, 2024 06:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants