From fd65561565844a0d23d846ba70fe428bba478e80 Mon Sep 17 00:00:00 2001 From: Loaner Date: Tue, 18 Jun 2024 10:12:52 -0700 Subject: [PATCH 01/24] adding support for coverage report --- app/build.gradle | 29 +++++++++++++++++++++++++++++ build.gradle | 20 ++++++++++++++++++++ sentry.properties | 2 +- 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index d41985be..39e25749 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,6 +12,7 @@ buildscript { plugins { id "io.sentry.android.gradle" version "4.4.0" + id "jacoco" } apply plugin: 'com.android.application' @@ -87,6 +88,34 @@ android { } +jacoco { + toolVersion = "0.8.5" +} + +task jacocoTestReport(type: JacocoReport) { + dependsOn 'testDebugUnitTest' // Use 'testDebugUnitTest' for unit tests in the debug build type + + reports { + xml.enabled = true + html.enabled = true + } + + def fileFilter = [ + '**/R.class', + '**/R$*.class', + '**/BuildConfig.*', + '**/Manifest*.*', + '**/*Test*.*' + ] + + def debugTree = fileTree(dir: "${buildDir}/intermediates/javac/debug", excludes: fileFilter) + def mainSrc = "${project.projectDir}/src/main/java" + + sourceDirectories.setFrom(files([mainSrc])) + classDirectories.setFrom(files([debugTree])) + executionData.setFrom(fileTree(dir: "${buildDir}/jacoco", includes: ["testDebugUnitTest.exec"])) +} + dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.1.0' diff --git a/build.gradle b/build.gradle index df093e4c..c10628bf 100644 --- a/build.gradle +++ b/build.gradle @@ -15,6 +15,24 @@ buildscript { } } +plugins { + id 'jacoco' +} + +//android { +// // Your existing configuration +// buildTypes { +// debug { +// testCoverageEnabled = true +// } +// } +//} + +jacoco { + toolVersion = "0.8.5" +} + + allprojects { repositories { google() @@ -25,3 +43,5 @@ allprojects { task clean(type: Delete) { delete rootProject.buildDir } + + diff --git a/sentry.properties b/sentry.properties index 90c17936..59c7401d 100644 --- a/sentry.properties +++ b/sentry.properties @@ -1,4 +1,4 @@ # how a sentry.properties looks like defaults.org=demo defaults.project=android -auth.token= +auth.token=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 From 4c35b6ab29855cd61de8274ec96de9e045cd21b8 Mon Sep 17 00:00:00 2001 From: yuval-sentry <89414234+yuval-sentry@users.noreply.github.com> Date: Tue, 18 Jun 2024 10:30:47 -0700 Subject: [PATCH 02/24] Create codecov-report.yml --- .github/workflows/codecov-report.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/workflows/codecov-report.yml diff --git a/.github/workflows/codecov-report.yml b/.github/workflows/codecov-report.yml new file mode 100644 index 00000000..ff722b7d --- /dev/null +++ b/.github/workflows/codecov-report.yml @@ -0,0 +1,10 @@ +# uploading codecov report + +ame: hello-world +on: [push, workflow_dispatch] +jobs: + my-job: + runs-on: ubuntu-latest + steps: + - name: my-step + run: echo "Hello World!" From 4154fd87fe38b1e78390e22b0b3ca91ee7c11f20 Mon Sep 17 00:00:00 2001 From: yuval-sentry <89414234+yuval-sentry@users.noreply.github.com> Date: Tue, 18 Jun 2024 10:31:35 -0700 Subject: [PATCH 03/24] Update codecov-report.yml --- .github/workflows/codecov-report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codecov-report.yml b/.github/workflows/codecov-report.yml index ff722b7d..4bdd33c7 100644 --- a/.github/workflows/codecov-report.yml +++ b/.github/workflows/codecov-report.yml @@ -1,6 +1,6 @@ # uploading codecov report -ame: hello-world +name: hello-world on: [push, workflow_dispatch] jobs: my-job: From d5f80250d01e11aa1d444a38fc8d7f69416f58ab Mon Sep 17 00:00:00 2001 From: Loaner Date: Tue, 18 Jun 2024 11:24:38 -0700 Subject: [PATCH 04/24] update jacoco config --- app/build.gradle | 11 +- .../example/vu/android/MainActivityTest.java | 112 +++++++++++++++++- build.gradle | 4 +- 3 files changed, 118 insertions(+), 9 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 39e25749..1a48fa1e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -93,7 +93,7 @@ jacoco { } task jacocoTestReport(type: JacocoReport) { - dependsOn 'testDebugUnitTest' // Use 'testDebugUnitTest' for unit tests in the debug build type + dependsOn 'connectedDebugAndroidTest' // Use 'testDebugUnitTest' for unit tests in the debug build type reports { xml.enabled = true @@ -113,7 +113,7 @@ task jacocoTestReport(type: JacocoReport) { sourceDirectories.setFrom(files([mainSrc])) classDirectories.setFrom(files([debugTree])) - executionData.setFrom(fileTree(dir: "${buildDir}/jacoco", includes: ["testDebugUnitTest.exec"])) + executionData.setFrom(fileTree(dir: "${buildDir}/outputs/code_coverage/debugAndroidTest/connected", includes: ["*.ec"])) } dependencies { @@ -127,9 +127,16 @@ dependencies { implementation 'com.squareup.okhttp3:okhttp:4.9.0' implementation 'junit:junit:4.12' implementation 'com.google.code.gson:gson:2.10.1' + implementation 'androidx.test:core:1.5.0' + implementation 'androidx.test.ext:junit:1.1.5' + implementation 'androidx.test.espresso:espresso-core:3.5.1' def fragment_version = "1.5.6" // Java language implementation implementation "androidx.fragment:fragment:$fragment_version" + implementation 'androidx.test:rules:1.4.0' + implementation 'org.mockito:mockito-core:3.11.2' + implementation 'org.mockito:mockito-android:3.11.2' + //implementation 'io.sentry:sentry-android:5.4.0' // Warning: upgrading the room version beyond 2.0.0 may // cause errors running automated Saucelabs tests that generate data. diff --git a/app/src/main/java/com/example/vu/android/MainActivityTest.java b/app/src/main/java/com/example/vu/android/MainActivityTest.java index a47d586c..ccda1d73 100644 --- a/app/src/main/java/com/example/vu/android/MainActivityTest.java +++ b/app/src/main/java/com/example/vu/android/MainActivityTest.java @@ -1,11 +1,113 @@ package com.example.vu.android; -import static org.junit.Assert.*; +import android.content.Intent; +//import androidx.test.core.app.ActivityScenario; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.rule.ActivityTestRule; +import androidx.test.espresso.Espresso; +import androidx.test.espresso.action.ViewActions; +import androidx.test.espresso.assertion.ViewAssertions; +import androidx.test.espresso.matcher.ViewMatchers; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import io.sentry.Sentry; + +@RunWith(AndroidJUnit4.class) public class MainActivityTest { - @org.junit.Test - public void dummyFunction() { - assertTrue(MainActivity.dummyFunction(false)); + @Rule + public ActivityTestRule activityRule = + new ActivityTestRule<>(MainActivity.class); + + @Test + public void testUnhandledArithmeticException() { + Espresso.onView(ViewMatchers.withId(R.id.div_zero)) + .perform(ViewActions.click()); + + // You might need to handle the exception and verify it was captured by Sentry + // Example: verify that Sentry captured the ArithmeticException + } + + @Test + public void testUnhandledNegativeArraySizeException() { + Espresso.onView(ViewMatchers.withId(R.id.negative_index)) + .perform(ViewActions.click()); + + // You might need to handle the exception and verify it was captured by Sentry + // Example: verify that Sentry captured the NegativeArraySizeException + } + + @Test + public void testHandledArrayIndexOutOfBoundsException() { + Espresso.onView(ViewMatchers.withId(R.id.handled_exception)) + .perform(ViewActions.click()); + + // Verify that Sentry captured the ArrayIndexOutOfBoundsException + } + + @Test + public void testANRButton() { + Espresso.onView(ViewMatchers.withId(R.id.anr)) + .perform(ViewActions.click()); + + // Verify that the UI is frozen (ANR) + } + + @Test + public void testNativeCrash() { + Espresso.onView(ViewMatchers.withId(R.id.native_crash)) + .perform(ViewActions.click()); + + // Verify that the native crash occurred } -} \ No newline at end of file + + @Test + public void testNativeMessage() { + Espresso.onView(ViewMatchers.withId(R.id.native_message)) + .perform(ViewActions.click()); + + // Verify that the native message was handled + } + + @Test + public void testError404() { + Espresso.onView(ViewMatchers.withId(R.id.error_404)) + .perform(ViewActions.click()); + + // Verify that the HTTP request was made + } + + @Test + public void testSlowRegexIssue() { + Espresso.onView(ViewMatchers.withId(R.id.slow_regex)) + .perform(ViewActions.click()); + + // Verify that the slow regex performance issue was logged + } + + @Test + public void testSlowImageDecodingIssue() { + Espresso.onView(ViewMatchers.withId(R.id.slow_image_decoding)) + .perform(ViewActions.click()); + + // Verify that the slow image decoding performance issue was logged + } + + @Test + public void testSlowJsonDecodingIssue() { + Espresso.onView(ViewMatchers.withId(R.id.slow_json_decoding)) + .perform(ViewActions.click()); + + // Verify that the slow json decoding performance issue was logged + } + +// @Test +// public void testDummyFunction() { +// boolean result = MainActivity.dummyFunction(false); +// assertTrue(result); +// } +} diff --git a/build.gradle b/build.gradle index c10628bf..27a32eb5 100644 --- a/build.gradle +++ b/build.gradle @@ -19,14 +19,14 @@ plugins { id 'jacoco' } -//android { +// android { // // Your existing configuration // buildTypes { // debug { // testCoverageEnabled = true // } // } -//} +// } jacoco { toolVersion = "0.8.5" From 1cb62d4263e95f7d190195c5ce4bed136ed2dfd9 Mon Sep 17 00:00:00 2001 From: Loaner Date: Tue, 18 Jun 2024 11:51:50 -0700 Subject: [PATCH 05/24] update codecov config --- app/build.gradle | 2 +- .../androidTest/java/MainActivityTest.java | 113 ++++++++++++++++++ gradle.properties | 3 +- 3 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 app/src/androidTest/java/MainActivityTest.java diff --git a/app/build.gradle b/app/build.gradle index 1a48fa1e..f283eabd 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -93,7 +93,7 @@ jacoco { } task jacocoTestReport(type: JacocoReport) { - dependsOn 'connectedDebugAndroidTest' // Use 'testDebugUnitTest' for unit tests in the debug build type + dependsOn 'testDebugUnitTest' // Use 'testDebugUnitTest' for unit tests in the debug build type reports { xml.enabled = true diff --git a/app/src/androidTest/java/MainActivityTest.java b/app/src/androidTest/java/MainActivityTest.java new file mode 100644 index 00000000..ccda1d73 --- /dev/null +++ b/app/src/androidTest/java/MainActivityTest.java @@ -0,0 +1,113 @@ +package com.example.vu.android; + +import android.content.Intent; + +//import androidx.test.core.app.ActivityScenario; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.rule.ActivityTestRule; +import androidx.test.espresso.Espresso; +import androidx.test.espresso.action.ViewActions; +import androidx.test.espresso.assertion.ViewAssertions; +import androidx.test.espresso.matcher.ViewMatchers; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import io.sentry.Sentry; + +@RunWith(AndroidJUnit4.class) +public class MainActivityTest { + + @Rule + public ActivityTestRule activityRule = + new ActivityTestRule<>(MainActivity.class); + + @Test + public void testUnhandledArithmeticException() { + Espresso.onView(ViewMatchers.withId(R.id.div_zero)) + .perform(ViewActions.click()); + + // You might need to handle the exception and verify it was captured by Sentry + // Example: verify that Sentry captured the ArithmeticException + } + + @Test + public void testUnhandledNegativeArraySizeException() { + Espresso.onView(ViewMatchers.withId(R.id.negative_index)) + .perform(ViewActions.click()); + + // You might need to handle the exception and verify it was captured by Sentry + // Example: verify that Sentry captured the NegativeArraySizeException + } + + @Test + public void testHandledArrayIndexOutOfBoundsException() { + Espresso.onView(ViewMatchers.withId(R.id.handled_exception)) + .perform(ViewActions.click()); + + // Verify that Sentry captured the ArrayIndexOutOfBoundsException + } + + @Test + public void testANRButton() { + Espresso.onView(ViewMatchers.withId(R.id.anr)) + .perform(ViewActions.click()); + + // Verify that the UI is frozen (ANR) + } + + @Test + public void testNativeCrash() { + Espresso.onView(ViewMatchers.withId(R.id.native_crash)) + .perform(ViewActions.click()); + + // Verify that the native crash occurred + } + + @Test + public void testNativeMessage() { + Espresso.onView(ViewMatchers.withId(R.id.native_message)) + .perform(ViewActions.click()); + + // Verify that the native message was handled + } + + @Test + public void testError404() { + Espresso.onView(ViewMatchers.withId(R.id.error_404)) + .perform(ViewActions.click()); + + // Verify that the HTTP request was made + } + + @Test + public void testSlowRegexIssue() { + Espresso.onView(ViewMatchers.withId(R.id.slow_regex)) + .perform(ViewActions.click()); + + // Verify that the slow regex performance issue was logged + } + + @Test + public void testSlowImageDecodingIssue() { + Espresso.onView(ViewMatchers.withId(R.id.slow_image_decoding)) + .perform(ViewActions.click()); + + // Verify that the slow image decoding performance issue was logged + } + + @Test + public void testSlowJsonDecodingIssue() { + Espresso.onView(ViewMatchers.withId(R.id.slow_json_decoding)) + .perform(ViewActions.click()); + + // Verify that the slow json decoding performance issue was logged + } + +// @Test +// public void testDummyFunction() { +// boolean result = MainActivity.dummyFunction(false); +// assertTrue(result); +// } +} diff --git a/gradle.properties b/gradle.properties index 706bcd15..0462d1a0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,4 +17,5 @@ org.gradle.jvmargs=-Xmx1536m # org.gradle.parallel=true android.useAndroidX=true -android.enableJetifier=true \ No newline at end of file +android.enableJetifier=true +org.gradle.caching=true \ No newline at end of file From e49c5b562920dba763187735540cb93bba70d538 Mon Sep 17 00:00:00 2001 From: Loaner Date: Tue, 18 Jun 2024 12:11:52 -0700 Subject: [PATCH 06/24] adding tests --- .../androidTest/java/MainFragmentTest.java | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 app/src/androidTest/java/MainFragmentTest.java diff --git a/app/src/androidTest/java/MainFragmentTest.java b/app/src/androidTest/java/MainFragmentTest.java new file mode 100644 index 00000000..d3933fe1 --- /dev/null +++ b/app/src/androidTest/java/MainFragmentTest.java @@ -0,0 +1,74 @@ +package com.example.vu.android.empowerplant; + +import android.app.Activity; +import android.app.ProgressDialog; +import android.content.Context; + +import androidx.fragment.app.testing.FragmentScenario; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.espresso.Espresso; +import androidx.test.espresso.action.ViewActions; +import androidx.test.espresso.assertion.ViewAssertions; +import androidx.test.espresso.matcher.ViewMatchers; + +import com.example.vu.android.R; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; + +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withText; + +@RunWith(AndroidJUnit4.class) +public class MainFragmentTest { + + @Rule + public FragmentScenario scenario = FragmentScenario.launchInContainer(MainFragment.class); + + private MockWebServer mockWebServer; + + @Before + public void setUp() throws Exception { + mockWebServer = new MockWebServer(); + mockWebServer.start(); + } + + @Test + public void testRecyclerViewIsDisplayed() { + Espresso.onView(withId(R.id.recyclerView)) + .check(ViewAssertions.matches(isDisplayed())); + } + + @Test + public void testFetchToolsFromServer() throws Exception { + MockResponse response = new MockResponse() + .setResponseCode(200) + .setBody("[{\"id\":1,\"title\":\"Item 1\",\"price\":100,\"imgcropped\":\"url1\"}]"); + mockWebServer.enqueue(response); + + scenario.onFragment(fragment -> { + fragment.END_POINT_PRODUCTS = mockWebServer.url("/products").toString(); + fragment.fetchToolsFromServer(); + }); + + Espresso.onView(withText("Item 1")) + .check(ViewAssertions.matches(isDisplayed())); + } + + @Test + public void testCheckoutButton() { + // Assuming there is a checkout button in the fragment's layout + Espresso.onView(withId(R.id.checkout_button)) + .perform(ViewActions.click()); + + // Verify the progress dialog is displayed + Espresso.onView(withText("Checking Out...")) + .check(ViewAssertions.matches(isDisplayed())); + } +} From 9c8e2ceaa05934e9d02a530e166108675d407e34 Mon Sep 17 00:00:00 2001 From: yuval-sentry <89414234+yuval-sentry@users.noreply.github.com> Date: Tue, 18 Jun 2024 13:44:35 -0700 Subject: [PATCH 07/24] Update codecov-report.yml --- .github/workflows/codecov-report.yml | 29 ++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/.github/workflows/codecov-report.yml b/.github/workflows/codecov-report.yml index 4bdd33c7..4ec8d52b 100644 --- a/.github/workflows/codecov-report.yml +++ b/.github/workflows/codecov-report.yml @@ -1,10 +1,27 @@ # uploading codecov report -name: hello-world -on: [push, workflow_dispatch] +name: Android + +on: [push, pull_request] + jobs: - my-job: - runs-on: ubuntu-latest + test: + runs-on: macOS-latest + steps: - - name: my-step - run: echo "Hello World!" + - uses: actions/checkout@v2 + - uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Build debug + run: bash ./gradlew build jacocoTestReport assembleAndroidTest + - name: run tests + uses: reactivecircus/android-emulator-runner@v1 + with: + api-level: 29 + script: ./gradlew connectedCheck + - name: Upload coverage to Codecov + run: | + curl -Os https://uploader.codecov.io/latest/macos/codecov + chmod +x codecov + ./codecov From 163b2fd681beb895e5357e98bcd004b253eb33d0 Mon Sep 17 00:00:00 2001 From: yuval-sentry <89414234+yuval-sentry@users.noreply.github.com> Date: Fri, 21 Jun 2024 08:24:02 -0700 Subject: [PATCH 08/24] Update codecov-report.yml --- .github/workflows/codecov-report.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codecov-report.yml b/.github/workflows/codecov-report.yml index 4ec8d52b..83d0b14c 100644 --- a/.github/workflows/codecov-report.yml +++ b/.github/workflows/codecov-report.yml @@ -1,6 +1,8 @@ # uploading codecov report name: Android +env: + CODECOV_TOKEN: ${{ 4b643ba1-1aaf-47a2-89cd-56f7d6ab45ad }} on: [push, pull_request] @@ -10,9 +12,10 @@ jobs: steps: - uses: actions/checkout@v2 - - uses: actions/setup-java@v1 + - uses: actions/setup-java@v2 with: - java-version: 1.8 + distribution: 'adopt' + java-version: 15.0.2 - name: Build debug run: bash ./gradlew build jacocoTestReport assembleAndroidTest - name: run tests From 43dfda5e98d2c90116b3505cc5a5556315fb1b8a Mon Sep 17 00:00:00 2001 From: yuval-sentry <89414234+yuval-sentry@users.noreply.github.com> Date: Fri, 21 Jun 2024 08:26:31 -0700 Subject: [PATCH 09/24] Update codecov-report.yml --- .github/workflows/codecov-report.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/codecov-report.yml b/.github/workflows/codecov-report.yml index 83d0b14c..b1b5e8f9 100644 --- a/.github/workflows/codecov-report.yml +++ b/.github/workflows/codecov-report.yml @@ -1,8 +1,6 @@ # uploading codecov report name: Android -env: - CODECOV_TOKEN: ${{ 4b643ba1-1aaf-47a2-89cd-56f7d6ab45ad }} on: [push, pull_request] From d28289e1b26950aeed5045e867d83872c9fbcf59 Mon Sep 17 00:00:00 2001 From: Loaner Date: Fri, 21 Jun 2024 08:36:02 -0700 Subject: [PATCH 10/24] removing file --- .../androidTest/java/MainFragmentTest.java | 74 ------------------- 1 file changed, 74 deletions(-) delete mode 100644 app/src/androidTest/java/MainFragmentTest.java diff --git a/app/src/androidTest/java/MainFragmentTest.java b/app/src/androidTest/java/MainFragmentTest.java deleted file mode 100644 index d3933fe1..00000000 --- a/app/src/androidTest/java/MainFragmentTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.example.vu.android.empowerplant; - -import android.app.Activity; -import android.app.ProgressDialog; -import android.content.Context; - -import androidx.fragment.app.testing.FragmentScenario; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.espresso.Espresso; -import androidx.test.espresso.action.ViewActions; -import androidx.test.espresso.assertion.ViewAssertions; -import androidx.test.espresso.matcher.ViewMatchers; - -import com.example.vu.android.R; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; - -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withText; - -@RunWith(AndroidJUnit4.class) -public class MainFragmentTest { - - @Rule - public FragmentScenario scenario = FragmentScenario.launchInContainer(MainFragment.class); - - private MockWebServer mockWebServer; - - @Before - public void setUp() throws Exception { - mockWebServer = new MockWebServer(); - mockWebServer.start(); - } - - @Test - public void testRecyclerViewIsDisplayed() { - Espresso.onView(withId(R.id.recyclerView)) - .check(ViewAssertions.matches(isDisplayed())); - } - - @Test - public void testFetchToolsFromServer() throws Exception { - MockResponse response = new MockResponse() - .setResponseCode(200) - .setBody("[{\"id\":1,\"title\":\"Item 1\",\"price\":100,\"imgcropped\":\"url1\"}]"); - mockWebServer.enqueue(response); - - scenario.onFragment(fragment -> { - fragment.END_POINT_PRODUCTS = mockWebServer.url("/products").toString(); - fragment.fetchToolsFromServer(); - }); - - Espresso.onView(withText("Item 1")) - .check(ViewAssertions.matches(isDisplayed())); - } - - @Test - public void testCheckoutButton() { - // Assuming there is a checkout button in the fragment's layout - Espresso.onView(withId(R.id.checkout_button)) - .perform(ViewActions.click()); - - // Verify the progress dialog is displayed - Espresso.onView(withText("Checking Out...")) - .check(ViewAssertions.matches(isDisplayed())); - } -} From 58c7809e31af6756de94369239c9cb8cef665c80 Mon Sep 17 00:00:00 2001 From: yuval-sentry <89414234+yuval-sentry@users.noreply.github.com> Date: Fri, 21 Jun 2024 08:40:14 -0700 Subject: [PATCH 11/24] Update codecov-report.yml --- .github/workflows/codecov-report.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/codecov-report.yml b/.github/workflows/codecov-report.yml index b1b5e8f9..8787a3a6 100644 --- a/.github/workflows/codecov-report.yml +++ b/.github/workflows/codecov-report.yml @@ -22,7 +22,9 @@ jobs: api-level: 29 script: ./gradlew connectedCheck - name: Upload coverage to Codecov + env: + CODECOV_TOKEN: 4b643ba1-1aaf-47a2-89cd-56f7d6ab45ad run: | curl -Os https://uploader.codecov.io/latest/macos/codecov chmod +x codecov - ./codecov + ./codecov -t $CODECOV_TOKEN From 97884596c4423021f64967e6e3f8fe4b7d7daeae Mon Sep 17 00:00:00 2001 From: yuval-sentry <89414234+yuval-sentry@users.noreply.github.com> Date: Fri, 21 Jun 2024 08:56:57 -0700 Subject: [PATCH 12/24] Update codecov-report.yml --- .github/workflows/codecov-report.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codecov-report.yml b/.github/workflows/codecov-report.yml index 8787a3a6..1f91c0ce 100644 --- a/.github/workflows/codecov-report.yml +++ b/.github/workflows/codecov-report.yml @@ -2,7 +2,14 @@ name: Android -on: [push, pull_request] +on: + # push: + # branches: + # - main + # pull_request: + # branches: + # - main + workflow_dispatch: # Allows manual triggering of the workflow jobs: test: @@ -13,7 +20,7 @@ jobs: - uses: actions/setup-java@v2 with: distribution: 'adopt' - java-version: 15.0.2 + java-version: 8 - name: Build debug run: bash ./gradlew build jacocoTestReport assembleAndroidTest - name: run tests From 052bf5ff593ef82788f3eedde16c2c651411cbe6 Mon Sep 17 00:00:00 2001 From: yuval-sentry <89414234+yuval-sentry@users.noreply.github.com> Date: Fri, 21 Jun 2024 08:58:06 -0700 Subject: [PATCH 13/24] Update codecov-report.yml --- .github/workflows/codecov-report.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/codecov-report.yml b/.github/workflows/codecov-report.yml index 1f91c0ce..622fa9d1 100644 --- a/.github/workflows/codecov-report.yml +++ b/.github/workflows/codecov-report.yml @@ -3,12 +3,12 @@ name: Android on: - # push: - # branches: - # - main - # pull_request: - # branches: - # - main + push: + branches: + - main + pull_request: + branches: + - main workflow_dispatch: # Allows manual triggering of the workflow jobs: From b75ede9bcb399a23b009d324d9ffcf4ab7bb63c7 Mon Sep 17 00:00:00 2001 From: yuval-sentry <89414234+yuval-sentry@users.noreply.github.com> Date: Fri, 21 Jun 2024 08:59:14 -0700 Subject: [PATCH 14/24] Update codecov-report.yml --- .github/workflows/codecov-report.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/codecov-report.yml b/.github/workflows/codecov-report.yml index 622fa9d1..74b6a7cc 100644 --- a/.github/workflows/codecov-report.yml +++ b/.github/workflows/codecov-report.yml @@ -2,14 +2,7 @@ name: Android -on: - push: - branches: - - main - pull_request: - branches: - - main - workflow_dispatch: # Allows manual triggering of the workflow +on: [push, pull_request] jobs: test: From 62c0b57a2827c1018cef4df7312ff2bf16d9b0dd Mon Sep 17 00:00:00 2001 From: Loaner Date: Fri, 21 Jun 2024 09:06:41 -0700 Subject: [PATCH 15/24] updating build.gradle --- app/build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index f283eabd..b14b7d30 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -130,6 +130,10 @@ dependencies { implementation 'androidx.test:core:1.5.0' implementation 'androidx.test.ext:junit:1.1.5' implementation 'androidx.test.espresso:espresso-core:3.5.1' + implementation 'javax.xml.bind:jaxb-api:2.3.1' + implementation 'org.glassfish.jaxb:jaxb-runtime:2.3.1' + implementation 'com.sun.activation:javax.activation:1.2.0' + def fragment_version = "1.5.6" // Java language implementation implementation "androidx.fragment:fragment:$fragment_version" From 976d871c06e8cc9ddcd339ef1714fcc7fd33dd02 Mon Sep 17 00:00:00 2001 From: yuval-sentry <89414234+yuval-sentry@users.noreply.github.com> Date: Fri, 21 Jun 2024 09:08:38 -0700 Subject: [PATCH 16/24] Update codecov-report.yml --- .github/workflows/codecov-report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codecov-report.yml b/.github/workflows/codecov-report.yml index 74b6a7cc..8787a3a6 100644 --- a/.github/workflows/codecov-report.yml +++ b/.github/workflows/codecov-report.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/setup-java@v2 with: distribution: 'adopt' - java-version: 8 + java-version: 15.0.2 - name: Build debug run: bash ./gradlew build jacocoTestReport assembleAndroidTest - name: run tests From a28f303e15bab4d2aada2927c802f2f9946340cc Mon Sep 17 00:00:00 2001 From: Loaner Date: Fri, 21 Jun 2024 09:16:04 -0700 Subject: [PATCH 17/24] removing unnecessary dependency --- app/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index b14b7d30..0c83b368 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -132,7 +132,6 @@ dependencies { implementation 'androidx.test.espresso:espresso-core:3.5.1' implementation 'javax.xml.bind:jaxb-api:2.3.1' implementation 'org.glassfish.jaxb:jaxb-runtime:2.3.1' - implementation 'com.sun.activation:javax.activation:1.2.0' def fragment_version = "1.5.6" // Java language implementation From 14a1d54d2f9fb0bb3b7322215171139abd86b96b Mon Sep 17 00:00:00 2001 From: yuval-sentry <89414234+yuval-sentry@users.noreply.github.com> Date: Fri, 21 Jun 2024 09:36:31 -0700 Subject: [PATCH 18/24] Update codecov-report.yml --- .github/workflows/codecov-report.yml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/codecov-report.yml b/.github/workflows/codecov-report.yml index 8787a3a6..72fb4f02 100644 --- a/.github/workflows/codecov-report.yml +++ b/.github/workflows/codecov-report.yml @@ -14,13 +14,9 @@ jobs: with: distribution: 'adopt' java-version: 15.0.2 - - name: Build debug - run: bash ./gradlew build jacocoTestReport assembleAndroidTest - - name: run tests - uses: reactivecircus/android-emulator-runner@v1 - with: - api-level: 29 - script: ./gradlew connectedCheck + - name: Build and run unit tests + run: | + ./gradlew build jacocoTestReport - name: Upload coverage to Codecov env: CODECOV_TOKEN: 4b643ba1-1aaf-47a2-89cd-56f7d6ab45ad From 36b6dca76f49d423c5cbaca77a32359c8902c875 Mon Sep 17 00:00:00 2001 From: yuval-sentry <89414234+yuval-sentry@users.noreply.github.com> Date: Fri, 21 Jun 2024 10:02:19 -0700 Subject: [PATCH 19/24] Update codecov-report.yml --- .github/workflows/codecov-report.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/codecov-report.yml b/.github/workflows/codecov-report.yml index 72fb4f02..4ec741f9 100644 --- a/.github/workflows/codecov-report.yml +++ b/.github/workflows/codecov-report.yml @@ -17,6 +17,10 @@ jobs: - name: Build and run unit tests run: | ./gradlew build jacocoTestReport + - name: List coverage report files + run: | + echo "Listing contents of build/reports/jacoco:" + ls -l build/reports/jacoco - name: Upload coverage to Codecov env: CODECOV_TOKEN: 4b643ba1-1aaf-47a2-89cd-56f7d6ab45ad From 68a5bdcb8211a54791491ae5fc27a9e7d43186d4 Mon Sep 17 00:00:00 2001 From: yuval-sentry <89414234+yuval-sentry@users.noreply.github.com> Date: Fri, 21 Jun 2024 10:17:00 -0700 Subject: [PATCH 20/24] Update codecov-report.yml --- .github/workflows/codecov-report.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/codecov-report.yml b/.github/workflows/codecov-report.yml index 4ec741f9..b6eb6e0c 100644 --- a/.github/workflows/codecov-report.yml +++ b/.github/workflows/codecov-report.yml @@ -21,10 +21,9 @@ jobs: run: | echo "Listing contents of build/reports/jacoco:" ls -l build/reports/jacoco - - name: Upload coverage to Codecov - env: - CODECOV_TOKEN: 4b643ba1-1aaf-47a2-89cd-56f7d6ab45ad - run: | - curl -Os https://uploader.codecov.io/latest/macos/codecov - chmod +x codecov - ./codecov -t $CODECOV_TOKEN + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: true + verbose: true From dc8e34a93334005153f021068751d3e251a7bac7 Mon Sep 17 00:00:00 2001 From: yuval-sentry <89414234+yuval-sentry@users.noreply.github.com> Date: Fri, 21 Jun 2024 10:26:23 -0700 Subject: [PATCH 21/24] Update codecov-report.yml --- .github/workflows/codecov-report.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/codecov-report.yml b/.github/workflows/codecov-report.yml index b6eb6e0c..e1dbf156 100644 --- a/.github/workflows/codecov-report.yml +++ b/.github/workflows/codecov-report.yml @@ -17,10 +17,6 @@ jobs: - name: Build and run unit tests run: | ./gradlew build jacocoTestReport - - name: List coverage report files - run: | - echo "Listing contents of build/reports/jacoco:" - ls -l build/reports/jacoco - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v4 with: From a2835eb3e379e70dffbca15d40ececc56ed263f2 Mon Sep 17 00:00:00 2001 From: Loaner Date: Fri, 21 Jun 2024 10:37:20 -0700 Subject: [PATCH 22/24] make sure report is always being generated --- app/build.gradle | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index 0c83b368..80e78e1c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -92,6 +92,10 @@ jacoco { toolVersion = "0.8.5" } +tasks.withType(Test) { + finalizedBy jacocoTestReport +} + task jacocoTestReport(type: JacocoReport) { dependsOn 'testDebugUnitTest' // Use 'testDebugUnitTest' for unit tests in the debug build type @@ -116,6 +120,11 @@ task jacocoTestReport(type: JacocoReport) { executionData.setFrom(fileTree(dir: "${buildDir}/outputs/code_coverage/debugAndroidTest/connected", includes: ["*.ec"])) } +tasks.named("jacocoTestReport") { + dependsOn "testDebugUnitTest" + onlyIf = { true } // Ensure the task is always executed +} + dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.1.0' From 7a718b8d756df305a5d3d607ca42a6bc501aaafe Mon Sep 17 00:00:00 2001 From: Loaner Date: Thu, 27 Jun 2024 20:38:22 -0700 Subject: [PATCH 23/24] update tests --- app/build.gradle | 76 +++++------ .../androidTest/java/MainActivityTest.java | 113 ---------------- .../androidTest/java/MainFragmentTest.java | 124 ++++++++++++++++++ app/src/androidTest/java/MockContext.java | 18 +++ .../example/vu/android/MainActivityTest.java | 113 ---------------- .../example/vu/android/MyApplicationTest.java | 14 -- app/src/test/java/MainFragmentTest.java | 32 +++++ app/src/test/java/MockContext.java | 18 +++ build.gradle | 23 +--- 9 files changed, 227 insertions(+), 304 deletions(-) delete mode 100644 app/src/androidTest/java/MainActivityTest.java create mode 100644 app/src/androidTest/java/MainFragmentTest.java create mode 100644 app/src/androidTest/java/MockContext.java delete mode 100644 app/src/main/java/com/example/vu/android/MainActivityTest.java delete mode 100644 app/src/main/java/com/example/vu/android/MyApplicationTest.java create mode 100644 app/src/test/java/MainFragmentTest.java create mode 100644 app/src/test/java/MockContext.java diff --git a/app/build.gradle b/app/build.gradle index 80e78e1c..933ac901 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,16 +1,19 @@ import io.sentry.android.gradle.instrumentation.logcat.LogcatLevel buildscript { - ext.kotlin_version= '1.8.20' - dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } + ext.kotlin_version = '1.8.20' repositories { mavenCentral() + google() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath 'com.android.tools.build:gradle:7.0.0' } } plugins { + id 'com.android.application' id "io.sentry.android.gradle" version "4.4.0" id "jacoco" } @@ -19,13 +22,6 @@ apply plugin: 'com.android.application' apply plugin: 'com.ydq.android.gradle.native-aar.import' apply plugin: 'io.sentry.android.gradle' apply plugin: 'kotlin-android' -//apply plugin: 'fullstory' - -//fullstory { -// org 'QNEN8' -// enabledVariants 'all' -// logLevel 'off' -//} task wrapper(type: org.gradle.api.tasks.wrapper.Wrapper) { gradleVersion = '7.0' @@ -55,6 +51,7 @@ android { ndk { abiFilters("x86", "armeabi-v7a", "x86_64", "arm64-v8a") } + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } externalNativeBuild { cmake { @@ -66,13 +63,13 @@ android { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - signingConfig = signingConfigs.debug // to be able to run release mode - buildConfigField("String", "SE", "\"tda\"") - buildConfigField("boolean", "SLOW_PROFILING", "true") + signingConfig signingConfigs.debug // to be able to run release mode + buildConfigField "String", "SE", "\"tda\"" + buildConfigField "boolean", "SLOW_PROFILING", "true" } debug { - buildConfigField("String", "SE", "\"tda\"") - buildConfigField("boolean", "SLOW_PROFILING", "true") + buildConfigField "String", "SE", "\"tda\"" + buildConfigField "boolean", "SLOW_PROFILING", "true" testCoverageEnabled true } } @@ -85,7 +82,6 @@ android { abortOnError false } ndkVersion '21.3.6528147' - } jacoco { @@ -97,7 +93,7 @@ tasks.withType(Test) { } task jacocoTestReport(type: JacocoReport) { - dependsOn 'testDebugUnitTest' // Use 'testDebugUnitTest' for unit tests in the debug build type + dependsOn 'testDebugUnitTest' reports { xml.enabled = true @@ -117,15 +113,21 @@ task jacocoTestReport(type: JacocoReport) { sourceDirectories.setFrom(files([mainSrc])) classDirectories.setFrom(files([debugTree])) - executionData.setFrom(fileTree(dir: "${buildDir}/outputs/code_coverage/debugAndroidTest/connected", includes: ["*.ec"])) + executionData.setFrom(fileTree(dir: "${buildDir}/jacoco/testDebugUnitTest.exec", includes: ["*.exec"])) } tasks.named("jacocoTestReport") { dependsOn "testDebugUnitTest" - onlyIf = { true } // Ensure the task is always executed + onlyIf = { true } } dependencies { + // Room components + def room_version = "2.0.0" + + implementation "androidx.room:room-runtime:$room_version" + annotationProcessor "androidx.room:room-compiler:$room_version" // For Java projects + implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.1.0' implementation group: 'androidx.constraintlayout', name: 'constraintlayout', version: '1.1.3' @@ -134,33 +136,21 @@ dependencies { implementation 'androidx.navigation:navigation-ui:2.5.3' implementation 'com.android.support:support-core-utils:28.0.0' implementation 'com.squareup.okhttp3:okhttp:4.9.0' - implementation 'junit:junit:4.12' implementation 'com.google.code.gson:gson:2.10.1' - implementation 'androidx.test:core:1.5.0' - implementation 'androidx.test.ext:junit:1.1.5' - implementation 'androidx.test.espresso:espresso-core:3.5.1' - implementation 'javax.xml.bind:jaxb-api:2.3.1' - implementation 'org.glassfish.jaxb:jaxb-runtime:2.3.1' - - def fragment_version = "1.5.6" - // Java language implementation - implementation "androidx.fragment:fragment:$fragment_version" - implementation 'androidx.test:rules:1.4.0' - implementation 'org.mockito:mockito-core:3.11.2' - implementation 'org.mockito:mockito-android:3.11.2' - //implementation 'io.sentry:sentry-android:5.4.0' - - // Warning: upgrading the room version beyond 2.0.0 may - // cause errors running automated Saucelabs tests that generate data. - // If you upgrade the room version, ensure you run associated automated - // tests locally and that they pass. - def room_version = "2.0.0" - - implementation "androidx.room:room-runtime:$room_version" - annotationProcessor "androidx.room:room-compiler:$room_version" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + + // Test dependencies + testImplementation 'junit:junit:4.13.2' + testImplementation 'org.mockito:mockito-core:3.11.2' + testImplementation 'org.mockito:mockito-inline:3.11.2' + testImplementation 'org.mockito:mockito-junit-jupiter:3.11.2' + + // Android Test dependencies + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' } + sentry { autoUpload = true uploadNativeSymbols = false diff --git a/app/src/androidTest/java/MainActivityTest.java b/app/src/androidTest/java/MainActivityTest.java deleted file mode 100644 index ccda1d73..00000000 --- a/app/src/androidTest/java/MainActivityTest.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.example.vu.android; - -import android.content.Intent; - -//import androidx.test.core.app.ActivityScenario; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.rule.ActivityTestRule; -import androidx.test.espresso.Espresso; -import androidx.test.espresso.action.ViewActions; -import androidx.test.espresso.assertion.ViewAssertions; -import androidx.test.espresso.matcher.ViewMatchers; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import io.sentry.Sentry; - -@RunWith(AndroidJUnit4.class) -public class MainActivityTest { - - @Rule - public ActivityTestRule activityRule = - new ActivityTestRule<>(MainActivity.class); - - @Test - public void testUnhandledArithmeticException() { - Espresso.onView(ViewMatchers.withId(R.id.div_zero)) - .perform(ViewActions.click()); - - // You might need to handle the exception and verify it was captured by Sentry - // Example: verify that Sentry captured the ArithmeticException - } - - @Test - public void testUnhandledNegativeArraySizeException() { - Espresso.onView(ViewMatchers.withId(R.id.negative_index)) - .perform(ViewActions.click()); - - // You might need to handle the exception and verify it was captured by Sentry - // Example: verify that Sentry captured the NegativeArraySizeException - } - - @Test - public void testHandledArrayIndexOutOfBoundsException() { - Espresso.onView(ViewMatchers.withId(R.id.handled_exception)) - .perform(ViewActions.click()); - - // Verify that Sentry captured the ArrayIndexOutOfBoundsException - } - - @Test - public void testANRButton() { - Espresso.onView(ViewMatchers.withId(R.id.anr)) - .perform(ViewActions.click()); - - // Verify that the UI is frozen (ANR) - } - - @Test - public void testNativeCrash() { - Espresso.onView(ViewMatchers.withId(R.id.native_crash)) - .perform(ViewActions.click()); - - // Verify that the native crash occurred - } - - @Test - public void testNativeMessage() { - Espresso.onView(ViewMatchers.withId(R.id.native_message)) - .perform(ViewActions.click()); - - // Verify that the native message was handled - } - - @Test - public void testError404() { - Espresso.onView(ViewMatchers.withId(R.id.error_404)) - .perform(ViewActions.click()); - - // Verify that the HTTP request was made - } - - @Test - public void testSlowRegexIssue() { - Espresso.onView(ViewMatchers.withId(R.id.slow_regex)) - .perform(ViewActions.click()); - - // Verify that the slow regex performance issue was logged - } - - @Test - public void testSlowImageDecodingIssue() { - Espresso.onView(ViewMatchers.withId(R.id.slow_image_decoding)) - .perform(ViewActions.click()); - - // Verify that the slow image decoding performance issue was logged - } - - @Test - public void testSlowJsonDecodingIssue() { - Espresso.onView(ViewMatchers.withId(R.id.slow_json_decoding)) - .perform(ViewActions.click()); - - // Verify that the slow json decoding performance issue was logged - } - -// @Test -// public void testDummyFunction() { -// boolean result = MainActivity.dummyFunction(false); -// assertTrue(result); -// } -} diff --git a/app/src/androidTest/java/MainFragmentTest.java b/app/src/androidTest/java/MainFragmentTest.java new file mode 100644 index 00000000..bc0fb916 --- /dev/null +++ b/app/src/androidTest/java/MainFragmentTest.java @@ -0,0 +1,124 @@ +package com.example.vu.android.empowerplant; + +import android.content.Context; +import android.os.Bundle; +import androidx.lifecycle.Lifecycle; +import io.sentry.ITransaction; +import io.sentry.Sentry; +import org.junit.Before; +import org.junit.Test; +import org.mockito.MockitoAnnotations; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; + +public class MainFragmentTest { + + private MainFragment mainFragment; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mainFragment = MainFragment.newInstance(); + } + + @Test + public void testMainFragmentNotNull() { + assertNotNull(mainFragment); + } + + @Test + public void testOnCreate() { + mainFragment.onCreate(null); + assertNotNull(mainFragment.getArguments()); + } + + @Test + public void testOnCreateView() { + assertNotNull(mainFragment.onCreateView(null, null, null)); + } + + @Test + public void testSetBadgeNumber() { + mainFragment.setBadgeNumber(); + // Assuming setBadgeNumber increases the badge number by 1 + assertEquals(1, mainFragment.mCartItemCount); + } + + @Test + public void testFetchToolsFromServer() { + mainFragment.fetchToolsFromServer(); + // Assuming fetchToolsFromServer fetches tools, we can check if the progress dialog is shown + assertNotNull(mainFragment.progressDialog); + assertTrue(mainFragment.progressDialog.isShowing()); + } + + @Test + public void testOnItemClick() { + StoreItem storeItem = new StoreItem(); + storeItem.setQuantity(1); + mainFragment.onItemClick(storeItem); + // Assuming onItemClick increases the item count + assertEquals(1, storeItem.getQuantity()); + } + + @Test + public void testProcessGetToolsResponse() { + mainFragment.processGetToolsResponse(""); + // Assuming processGetToolsResponse updates the adapter + assertNotNull(mainFragment.adapter); + } + + @Test + public void testProcessProducts() { + mainFragment.processProducts(); + // Assuming processProducts calls getIterator, which returns a value + assertEquals(1, mainFragment.getIterator(1)); + } + + @Test + public void testGetIterator() { + assertEquals(1, mainFragment.getIterator(1)); + } + + @Test + public void testGetEmpowerPlantDomain() { + assertNotNull(mainFragment.getEmpowerPlantDomain()); + } + + @Test + public void testCheckout() { + mainFragment.checkout(); + // Assuming checkout starts a transaction, check if the transaction is not null + ITransaction transaction = Sentry.startTransaction("checkout [android]", "http.client"); + assertNotNull(transaction); + } + + @Test + public void testBuildJSONPostData() { + HashMap storeItems = new HashMap<>(); + assertNotNull(mainFragment.buildJSONPostData(storeItems)); + } + + @Test + public void testProcessDeliveryItem() { + ITransaction transaction = Sentry.startTransaction("test", "test"); + mainFragment.processDeliveryItem(transaction); + // Assuming processDeliveryItem sets the status + assertEquals(transaction.getStatus(), SpanStatus.OK); + } + + @Test + public void testAddAttachment() { + assertTrue(mainFragment.addAttachment()); + } + + @Test + public void testInsertMultipleStoreItems() { + mainFragment.insertMultipleStoreItems(); + // Assuming insertMultipleStoreItems interacts with a database, this is harder to assert directly + } +} diff --git a/app/src/androidTest/java/MockContext.java b/app/src/androidTest/java/MockContext.java new file mode 100644 index 00000000..df3d356a --- /dev/null +++ b/app/src/androidTest/java/MockContext.java @@ -0,0 +1,18 @@ +package com.example.vu.android.empowerplant; + +import android.content.Context; +import android.content.ContextWrapper; + +public class MockContext extends ContextWrapper { + + public MockContext() { + super(null); + } + + @Override + public Context getApplicationContext() { + return this; + } + + // Add other methods if needed for your specific tests +} diff --git a/app/src/main/java/com/example/vu/android/MainActivityTest.java b/app/src/main/java/com/example/vu/android/MainActivityTest.java deleted file mode 100644 index ccda1d73..00000000 --- a/app/src/main/java/com/example/vu/android/MainActivityTest.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.example.vu.android; - -import android.content.Intent; - -//import androidx.test.core.app.ActivityScenario; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.rule.ActivityTestRule; -import androidx.test.espresso.Espresso; -import androidx.test.espresso.action.ViewActions; -import androidx.test.espresso.assertion.ViewAssertions; -import androidx.test.espresso.matcher.ViewMatchers; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import io.sentry.Sentry; - -@RunWith(AndroidJUnit4.class) -public class MainActivityTest { - - @Rule - public ActivityTestRule activityRule = - new ActivityTestRule<>(MainActivity.class); - - @Test - public void testUnhandledArithmeticException() { - Espresso.onView(ViewMatchers.withId(R.id.div_zero)) - .perform(ViewActions.click()); - - // You might need to handle the exception and verify it was captured by Sentry - // Example: verify that Sentry captured the ArithmeticException - } - - @Test - public void testUnhandledNegativeArraySizeException() { - Espresso.onView(ViewMatchers.withId(R.id.negative_index)) - .perform(ViewActions.click()); - - // You might need to handle the exception and verify it was captured by Sentry - // Example: verify that Sentry captured the NegativeArraySizeException - } - - @Test - public void testHandledArrayIndexOutOfBoundsException() { - Espresso.onView(ViewMatchers.withId(R.id.handled_exception)) - .perform(ViewActions.click()); - - // Verify that Sentry captured the ArrayIndexOutOfBoundsException - } - - @Test - public void testANRButton() { - Espresso.onView(ViewMatchers.withId(R.id.anr)) - .perform(ViewActions.click()); - - // Verify that the UI is frozen (ANR) - } - - @Test - public void testNativeCrash() { - Espresso.onView(ViewMatchers.withId(R.id.native_crash)) - .perform(ViewActions.click()); - - // Verify that the native crash occurred - } - - @Test - public void testNativeMessage() { - Espresso.onView(ViewMatchers.withId(R.id.native_message)) - .perform(ViewActions.click()); - - // Verify that the native message was handled - } - - @Test - public void testError404() { - Espresso.onView(ViewMatchers.withId(R.id.error_404)) - .perform(ViewActions.click()); - - // Verify that the HTTP request was made - } - - @Test - public void testSlowRegexIssue() { - Espresso.onView(ViewMatchers.withId(R.id.slow_regex)) - .perform(ViewActions.click()); - - // Verify that the slow regex performance issue was logged - } - - @Test - public void testSlowImageDecodingIssue() { - Espresso.onView(ViewMatchers.withId(R.id.slow_image_decoding)) - .perform(ViewActions.click()); - - // Verify that the slow image decoding performance issue was logged - } - - @Test - public void testSlowJsonDecodingIssue() { - Espresso.onView(ViewMatchers.withId(R.id.slow_json_decoding)) - .perform(ViewActions.click()); - - // Verify that the slow json decoding performance issue was logged - } - -// @Test -// public void testDummyFunction() { -// boolean result = MainActivity.dummyFunction(false); -// assertTrue(result); -// } -} diff --git a/app/src/main/java/com/example/vu/android/MyApplicationTest.java b/app/src/main/java/com/example/vu/android/MyApplicationTest.java deleted file mode 100644 index 4ad3379b..00000000 --- a/app/src/main/java/com/example/vu/android/MyApplicationTest.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.example.vu.android; - -import static org.junit.Assert.*; - -import org.junit.Test; - -public class MyApplicationTest { - - @org.junit.Test - public void getcurrentactivity() { - MyApplication app = new MyApplication(); - assertEquals(app.getCurrentActivity(), null); - } -} \ No newline at end of file diff --git a/app/src/test/java/MainFragmentTest.java b/app/src/test/java/MainFragmentTest.java new file mode 100644 index 00000000..8791ed87 --- /dev/null +++ b/app/src/test/java/MainFragmentTest.java @@ -0,0 +1,32 @@ +package com.example.vu.android.empowerplant; + +import android.content.Context; +import android.os.Bundle; +import androidx.lifecycle.Lifecycle; +import io.sentry.ITransaction; +import io.sentry.Sentry; +import org.junit.Before; +import org.junit.Test; +import org.mockito.MockitoAnnotations; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; + +public class MainFragmentTest { + + private MainFragment mainFragment; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mainFragment = MainFragment.newInstance(); + } + + @Test + public void testMainFragmentNotNull() { + assertNotNull(mainFragment); + } +} diff --git a/app/src/test/java/MockContext.java b/app/src/test/java/MockContext.java new file mode 100644 index 00000000..df3d356a --- /dev/null +++ b/app/src/test/java/MockContext.java @@ -0,0 +1,18 @@ +package com.example.vu.android.empowerplant; + +import android.content.Context; +import android.content.ContextWrapper; + +public class MockContext extends ContextWrapper { + + public MockContext() { + super(null); + } + + @Override + public Context getApplicationContext() { + return this; + } + + // Add other methods if needed for your specific tests +} diff --git a/build.gradle b/build.gradle index 27a32eb5..397c4f7e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,6 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - repositories { google() jcenter() @@ -12,36 +11,18 @@ buildscript { classpath 'com.android.tools.build:gradle:7.0.3' classpath 'com.ydq.android.gradle.build.tool:nativeBundle:1.0.7' classpath 'com.fullstory:gradle-plugin-local:1.12.1' + classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.20' } } -plugins { - id 'jacoco' -} - -// android { -// // Your existing configuration -// buildTypes { -// debug { -// testCoverageEnabled = true -// } -// } -// } - -jacoco { - toolVersion = "0.8.5" -} - - allprojects { repositories { google() jcenter() + mavenCentral() } } task clean(type: Delete) { delete rootProject.buildDir } - - From 6afb3e1db3921af3440a32bb356990c2d41317e7 Mon Sep 17 00:00:00 2001 From: Loaner Date: Thu, 27 Jun 2024 21:14:09 -0700 Subject: [PATCH 24/24] add tests --- .../vu/android/empowerplant/MainFragment.java | 9 ++++++ app/src/test/java/MainFragmentTest.java | 31 +++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/example/vu/android/empowerplant/MainFragment.java b/app/src/main/java/com/example/vu/android/empowerplant/MainFragment.java index 5e119cb0..f679dee5 100644 --- a/app/src/main/java/com/example/vu/android/empowerplant/MainFragment.java +++ b/app/src/main/java/com/example/vu/android/empowerplant/MainFragment.java @@ -258,6 +258,15 @@ private int getIterator(int n) { return getIterator(n-1) + getIterator(n-2); } + public int getNumber() { + int result = getAnotherNumber(); + return result; + } + + public int getAnotherNumber() { + return 2; + } + private String getEmpowerPlantDomain() { String domain = null; try { diff --git a/app/src/test/java/MainFragmentTest.java b/app/src/test/java/MainFragmentTest.java index 8791ed87..a57bc6bc 100644 --- a/app/src/test/java/MainFragmentTest.java +++ b/app/src/test/java/MainFragmentTest.java @@ -7,11 +7,16 @@ import io.sentry.Sentry; import org.junit.Before; import org.junit.Test; -import org.mockito.MockitoAnnotations; +import org.mockito.*; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + import java.util.HashMap; @@ -22,11 +27,33 @@ public class MainFragmentTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); - mainFragment = MainFragment.newInstance(); + mainFragment = spy(MainFragment.newInstance()); } @Test public void testMainFragmentNotNull() { assertNotNull(mainFragment); } + + @Test + public void testGetNumber() { + // Given + doReturn(2).when(mainFragment).getAnotherNumber(); + + // When + int result = mainFragment.getNumber(); + + // Then + assertEquals(2, result); + verify(mainFragment, times(1)).getAnotherNumber(); + } + + @Test + public void testGetAnotherNumber() { + // When + int result = mainFragment.getAnotherNumber(); + + // Then + assertEquals(2, result); + } }