-
Notifications
You must be signed in to change notification settings - Fork 61
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
RUM-5525 Add the integration tests for the SdkCore APIs #2145
RUM-5525 Add the integration tests for the SdkCore APIs #2145
Conversation
b1cc80f
to
89364ed
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## develop #2145 +/- ##
===========================================
+ Coverage 69.98% 70.03% +0.05%
===========================================
Files 726 726
Lines 27001 26996 -5
Branches 4525 4524 -1
===========================================
+ Hits 18895 18904 +9
+ Misses 6836 6829 -7
+ Partials 1270 1263 -7 |
buildTypes { | ||
getByName("release") { | ||
isMinifyEnabled = true | ||
proguardFiles( | ||
getDefaultProguardFile("proguard-android-optimize.txt"), | ||
"proguard-rules.pro" | ||
) | ||
testProguardFile("test-proguard-rules.pro") | ||
} | ||
getByName("debug") { | ||
isMinifyEnabled = true | ||
proguardFiles( | ||
getDefaultProguardFile("proguard-android-optimize.txt"), | ||
"proguard-rules.pro" | ||
) | ||
testProguardFile("test-proguard-rules.pro") | ||
} |
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.
Note
Why do you need a release build, and why minify both release and debug ?
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 trying to test these in the same conditions as a normal app. We did the same for integration tests. Not sure is the best approach but I think it is better.
private var fakeUserId: String? = null | ||
private var fakeUserName: String? = null | ||
private var fakeUserEmail: String? = null | ||
private var fakeUserAdditionalProperties: Map<String, Any?> = emptyMap() | ||
private lateinit var stubFeature: StorageBackedFeature | ||
private lateinit var fakeFeatureName: String |
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.
Note
The @[…]Forgery
annotations work in JUnit4 too, so you could use that instead of manual forgeries in the setUp()
method.
class SdkCoreTest : MockServerTest() { | ||
|
||
@get:Rule | ||
var forge = ForgeRule() |
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.
var forge = ForgeRule() | |
var forge = ForgeRule() | |
.useJvmFactories() | |
.useToolsFactories() | |
.withFactory(ConfigurationCoreForgeryFactory() |
ConditionWatcher { | ||
var readUserInfo: UserInfo? = null | ||
featureSdkCore?.getFeature(stubFeature.name)?.withWriteContext { datadogContext, _ -> | ||
readUserInfo = datadogContext.userInfo | ||
} | ||
assertThat(readUserInfo?.id).isEqualTo(fakeUserId) | ||
assertThat(readUserInfo?.name).isEqualTo(fakeUserName) | ||
assertThat(readUserInfo?.email).isEqualTo(fakeUserEmail) | ||
assertThat(readUserInfo?.additionalProperties) | ||
.containsExactlyInAnyOrderEntriesOf(fakeUserAdditionalProperties) | ||
true | ||
}.doWait(timeoutMs = FINAL_WAIT_MS) |
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.
Important
Is a 30 seconds wait really necessary here ? We're not writing anything to disk, and this could hide a problem if setting the user info actually gets delayed more than acceptable amount of time.
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.
it is max 30 seconds, same approach we have in the integration tests now. I am not actually sure we are not writing on disk as the UserInfoProvider
writes on the disk first. I am going to check if we use also the RAM in addition to that for the current process.
assertThat(readUserInfo?.additionalProperties) | ||
.containsExactlyInAnyOrderEntriesOf(fakeUserAdditionalProperties + expectedUserExtraProperties) | ||
true | ||
}.doWait(timeoutMs = FINAL_WAIT_MS) |
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.
Same here
assertThat(datadogContext.trackingConsent).isEqualTo(expectedTrackingConsent) | ||
} | ||
true | ||
}.doWait(timeoutMs = FINAL_WAIT_MS) |
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.
Same here
89364ed
to
f9a4c8e
Compare
5eba221
to
07b92b7
Compare
abstract class BaseTest { | ||
|
||
companion object { | ||
internal val LONG_WAIT_MS = TimeUnit.SECONDS.toMillis(30) |
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 don't see this being used anywhere anymore. Can it be removed?
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 might use it later as some use - cases will require it (waiting for messages to be send through mock server). I would rather keep fit for now and decide later.
val configuration: Configuration = forge.getForgery() | ||
val sdkCore = Datadog.initialize( | ||
ApplicationProvider.getApplicationContext(), | ||
configuration, | ||
forge.aValueFrom(TrackingConsent::class.java) | ||
) | ||
val featureSdkCore = sdkCore as? FeatureSdkCore | ||
featureSdkCore?.registerFeature(stubFeature) |
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.
Note
Shouldn't this be part of the setup
?
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.
yup we could add it there
val countDownLatch = CountDownLatch(1) | ||
var readUserInfo: UserInfo? = null | ||
featureSdkCore?.getFeature(stubFeature.name)?.withWriteContext { datadogContext, _ -> | ||
readUserInfo = datadogContext.userInfo | ||
countDownLatch.countDown() | ||
} | ||
countDownLatch.await(SHORT_WAIT_MS, TimeUnit.MILLISECONDS) | ||
assertThat(readUserInfo?.id).isEqualTo(fakeUserId) | ||
assertThat(readUserInfo?.name).isEqualTo(fakeUserName) | ||
assertThat(readUserInfo?.email).isEqualTo(fakeUserEmail) | ||
assertThat(readUserInfo?.additionalProperties) | ||
.containsExactlyInAnyOrderEntriesOf(fakeUserAdditionalProperties) |
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.
👍 Much Better
// region add User Properties | ||
|
||
@Test | ||
fun must_addUserExtraProperties_when_addUserProperties() { |
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.
Note
You need another test when you don't call setUserInfo
first, and probably another ones where you overwrite values too (both overriding a value set from setUserInfo
and a value set from addUserProperties
.
// region set Tracking Consent | ||
|
||
@Test | ||
fun must_updateTrackingConsent_when_setTrackingConsent() { |
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.
Note
You need another test to verify that the value you get is the one from initialize
when you don't update it.
import java.util.concurrent.TimeUnit | ||
|
||
@RunWith(AndroidJUnit4::class) | ||
class SdkCoreTest : MockServerTest() { |
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.
Note
To make tests easier, we can split the core test by scopes, and name the test classes accordingly
SdkCoreInformation
(not really sure about the name here) for the current one, to test data that's kept in memory (user info, global attributes, tracking consent, …) used by featuresSdkCoreIO
(maybe with variants based on Tracking consent:…Granted
,…Denied
,…Pending
,…PendingToGranted
,…PendingToDenied
, …) to test that data sent to the core is dealt with accordingly- … ?
def6157
to
85fb24b
Compare
85fb24b
to
ed62d5f
Compare
private lateinit var fakeTrackingConsent: TrackingConsent | ||
|
||
private var featureSdkCore: FeatureSdkCore? = null | ||
private var sdkCore: SdkCore? = null |
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.
Note
Nit pick, as per our guidelines it should be named testedSdkCore
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.
will change it in my next PR
|
||
private lateinit var fakeTrackingConsent: TrackingConsent | ||
|
||
private var featureSdkCore: FeatureSdkCore? = null |
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.
better to use lateinit var
with non-nullable type. Will remove a lot of .?
in the code.
keepStartingWith("org.json") | ||
androidTestImplementation(project(":reliability:stub-feature")) | ||
androidTestImplementation(libs.assertJ) | ||
androidTestImplementation(libs.mockitoAndroid) |
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 cannot see any usages of that. Is it really needed?
What does this PR do?
In this PR we are adding the integrations tests to cover the SdkCore public API. In addition to that we are introducing the
StubStorageBackedFeature
which will be leveraged in order to assert expected behaviours of the core module during the integration tests.Motivation
What inspired you to submit this pull request?
Additional Notes
Anything else we should know when reviewing?
Review checklist (to be filled by reviewers)