Skip to content

Commit 608073d

Browse files
Merge pull request #97 from contentstack/fix/dx-3678-improve-tests
Fix/dx 3678 improve tests
2 parents 5ea5b09 + 7861c1e commit 608073d

File tree

73 files changed

+27957
-46
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+27957
-46
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
buildscript {
22
ext {
3-
jacoco_version = '0.8.8'
3+
jacoco_version = '0.8.12'
44
agp_version = '8.2.1'
55
}
66
repositories {

contentstack/build.gradle

Lines changed: 200 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
plugins {
22
id "com.android.library"
33
id "com.vanniktech.maven.publish" version "0.33.0"
4+
id 'jacoco'
45
}
56

67
ext {
@@ -12,6 +13,15 @@ ext {
1213
android {
1314
namespace "com.contentstack.sdk"
1415
compileSdk 34 // Using latest stable Android SDK version
16+
17+
// SDK compiles to Java 17 for JaCoCo compatibility
18+
// But can be built with Java 21 - tests use Java 17 toolchain
19+
compileOptions {
20+
coreLibraryDesugaringEnabled true
21+
sourceCompatibility JavaVersion.VERSION_17
22+
targetCompatibility JavaVersion.VERSION_17
23+
}
24+
1525
buildFeatures {
1626
buildConfig true
1727
}
@@ -30,10 +40,15 @@ android {
3040
}
3141

3242
testOptions {
33-
unitTests.all {
34-
// jacoco {
35-
// includeNoLocationClasses = true
36-
// }
43+
unitTests {
44+
includeAndroidResources = true
45+
returnDefaultValues = true
46+
all {
47+
jacoco {
48+
includeNoLocationClasses = true
49+
excludes = ['jdk.internal.*']
50+
}
51+
}
3752
}
3853
}
3954
// signing {
@@ -109,18 +124,37 @@ dependencies {
109124
def multidex = "2.0.1"
110125
def volley = "1.2.1"
111126
def junit = "4.13.2"
127+
def mockito = "5.2.0"
128+
def mockitoKotlin = "2.2.0"
112129
configurations.configureEach { resolutionStrategy.force 'com.android.support:support-annotations:23.1.0' }
113130
implementation fileTree(include: ['*.jar'], dir: 'libs')
114131
implementation "com.android.volley:volley:$volley"
115132
implementation "junit:junit:$junit"
116133

117134
// For AGP 7.4+
118135
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
136+
137+
// Unit Testing Dependencies
119138
testImplementation 'junit:junit:4.13.2'
139+
testImplementation "org.mockito:mockito-core:$mockito"
140+
testImplementation "org.mockito:mockito-inline:$mockito"
141+
testImplementation 'org.mockito:mockito-android:5.2.0'
142+
testImplementation 'org.robolectric:robolectric:4.15' // Updated to fix security vulnerabilities
143+
testImplementation 'androidx.test:core:1.5.0'
144+
testImplementation 'androidx.test:runner:1.5.2'
145+
testImplementation 'androidx.test.ext:junit:1.1.5'
146+
testImplementation 'com.squareup.okhttp3:mockwebserver:4.12.0'
147+
testImplementation 'org.json:json:20231013'
148+
// PowerMock for advanced mocking
149+
testImplementation 'org.powermock:powermock-module-junit4:2.0.9'
150+
testImplementation 'org.powermock:powermock-api-mockito2:2.0.9'
151+
testImplementation 'org.powermock:powermock-core:2.0.9'
152+
153+
// Android Test Dependencies
120154
androidTestImplementation 'androidx.test:core:1.5.0'
121-
testImplementation 'org.robolectric:robolectric:4.6.1'
122-
123-
androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0', {
155+
androidTestImplementation 'androidx.test:runner:1.5.2'
156+
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
157+
androidTestImplementation('androidx.test.espresso:espresso-core:3.5.1', {
124158
exclude group: 'com.android.support', module: 'support-annotations'
125159
})
126160

@@ -200,22 +234,170 @@ mavenPublishing {
200234
}
201235
}
202236

237+
jacoco {
238+
toolVersion = "0.8.12"
239+
}
240+
203241
tasks.register('jacocoTestReport', JacocoReport) {
204-
dependsOn('testDebugUnitTest', 'createDebugCoverageReport')
242+
dependsOn('testDebugUnitTest')
243+
205244
reports {
245+
xml.required = true
206246
html.required = true
247+
csv.required = false
248+
249+
xml.outputLocation = file("${buildDir}/reports/jacoco/jacocoTestReport/jacocoTestReport.xml")
250+
html.outputLocation = file("${buildDir}/reports/jacoco/jacocoTestReport/html")
207251
}
252+
253+
def excludePatterns = [
254+
'**/R.class',
255+
'**/R$*.class',
256+
'**/BuildConfig.*',
257+
'**/Manifest*.*',
258+
'**/*Test*.*',
259+
'android/**/*.*',
260+
'**/*$ViewInjector*.*',
261+
'**/*$ViewBinder*.*',
262+
'**/Lambda$*.class',
263+
'**/Lambda.class',
264+
'**/*Lambda.class',
265+
'**/*Lambda*.class',
266+
'**/*_MembersInjector.class',
267+
'**/Dagger*Component*.*',
268+
'**/*Module_*Factory.class',
269+
'**/AutoValue_*.*',
270+
'**/*JavascriptBridge.class',
271+
'**/package-info.class',
272+
'**/TestActivity.class',
273+
// External library exclusions
274+
'**/okhttp/**',
275+
'**/okio/**',
276+
'**/txtmark/**',
277+
'**/retrofit2/**',
278+
'**/volley/**',
279+
'**/CSConnectionRequest.class',
280+
// Exclude callback interfaces and their anonymous implementations
281+
'**/SyncResultCallBack.class',
282+
'**/Stack$*.class'
283+
]
284+
285+
sourceDirectories.setFrom(files([
286+
"${project.projectDir}/src/main/java"
287+
]))
288+
289+
classDirectories.setFrom(files([
290+
fileTree(dir: "${buildDir}/intermediates/javac/debug", excludes: excludePatterns),
291+
fileTree(dir: "${buildDir}/tmp/kotlin-classes/debug", excludes: excludePatterns)
292+
]))
293+
294+
executionData.setFrom(fileTree(buildDir).include([
295+
"outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec",
296+
"jacoco/testDebugUnitTest.exec"
297+
]))
208298
}
209299

210-
// Configure jacocoTestReport after evaluation when classDirectories is available
211-
project.afterEvaluate {
212-
tasks.named('jacocoTestReport', JacocoReport) {
213-
classDirectories.setFrom(files(classDirectories.files.collect {
214-
fileTree(dir: it, exclude: [
215-
'**com/contentstack/okhttp**',
216-
'**com/contentstack/okio**',
217-
'**com/contentstack/txtmark**'
218-
])
219-
}))
300+
// Combined coverage report for both unit and instrumentation tests
301+
tasks.register('jacocoCombinedReport', JacocoReport) {
302+
// This task can run after both test types complete
303+
// Make it depend on both if they're being run
304+
group = "Reporting"
305+
description = "Generate Jacoco coverage reports for both unit and instrumentation tests"
306+
307+
reports {
308+
xml.required = true
309+
html.required = true
310+
csv.required = false
311+
312+
xml.outputLocation = file("${buildDir}/reports/jacoco/jacocoCombinedReport/jacocoCombinedReport.xml")
313+
html.outputLocation = file("${buildDir}/reports/jacoco/jacocoCombinedReport/html")
220314
}
315+
316+
def excludePatterns = [
317+
'**/R.class',
318+
'**/R$*.class',
319+
'**/BuildConfig.*',
320+
'**/Manifest*.*',
321+
'**/*Test*.*',
322+
'android/**/*.*',
323+
'**/*$ViewInjector*.*',
324+
'**/*$ViewBinder*.*',
325+
'**/Lambda$*.class',
326+
'**/Lambda.class',
327+
'**/*Lambda.class',
328+
'**/*Lambda*.class',
329+
'**/*_MembersInjector.class',
330+
'**/Dagger*Component*.*',
331+
'**/*Module_*Factory.class',
332+
'**/AutoValue_*.*',
333+
'**/*JavascriptBridge.class',
334+
'**/package-info.class',
335+
'**/TestActivity.class',
336+
// External library exclusions
337+
'**/okhttp/**',
338+
'**/okio/**',
339+
'**/txtmark/**',
340+
'**/retrofit2/**',
341+
'**/volley/**',
342+
'**/CSConnectionRequest.class',
343+
// Exclude callback interfaces and their anonymous implementations
344+
'**/SyncResultCallBack.class',
345+
'**/Stack$*.class'
346+
]
347+
348+
sourceDirectories.setFrom(files([
349+
"${project.projectDir}/src/main/java"
350+
]))
351+
352+
classDirectories.setFrom(files([
353+
fileTree(dir: "${buildDir}/intermediates/javac/debug", excludes: excludePatterns),
354+
fileTree(dir: "${buildDir}/tmp/kotlin-classes/debug", excludes: excludePatterns)
355+
]))
356+
357+
// Collect execution data from both unit tests and instrumentation tests
358+
executionData.setFrom(fileTree(buildDir).include([
359+
// Unit test coverage
360+
"outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec",
361+
"jacoco/testDebugUnitTest.exec",
362+
// Instrumentation test coverage
363+
"outputs/code_coverage/debugAndroidTest/connected/**/*.ec"
364+
]))
365+
}
366+
367+
tasks.register('jacocoTestCoverageVerification', JacocoCoverageVerification) {
368+
dependsOn('testDebugUnitTest')
369+
370+
def excludePatterns = [
371+
'**/R.class',
372+
'**/R$*.class',
373+
'**/BuildConfig.*',
374+
'**/Manifest*.*',
375+
'**/*Test*.*',
376+
'android/**/*.*',
377+
'**/package-info.class',
378+
'**/TestActivity.class',
379+
'**/CSConnectionRequest.class',
380+
// Exclude callback interfaces and their anonymous implementations
381+
'**/SyncResultCallBack.class',
382+
'**/Stack$*.class'
383+
]
384+
385+
sourceDirectories.setFrom(files([
386+
"${project.projectDir}/src/main/java"
387+
]))
388+
389+
classDirectories.setFrom(files([
390+
fileTree(dir: "${buildDir}/intermediates/javac/debug", excludes: excludePatterns),
391+
fileTree(dir: "${buildDir}/tmp/kotlin-classes/debug", excludes: excludePatterns)
392+
]))
393+
394+
executionData.setFrom(fileTree(buildDir).include([
395+
"outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec",
396+
"jacoco/testDebugUnitTest.exec"
397+
]))
398+
}
399+
400+
// Make check task depend on coverage verification
401+
tasks.named('check') {
402+
dependsOn('jacocoTestReport', 'jacocoTestCoverageVerification')
221403
}

contentstack/src/main/java/com/contentstack/sdk/TestActivity.java

Lines changed: 0 additions & 13 deletions
This file was deleted.

contentstack/src/test/java/com/contentstack/sdk/ExampleUnitTest.java

Lines changed: 0 additions & 13 deletions
This file was deleted.

0 commit comments

Comments
 (0)