diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..3765039 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @kamildziadek @viclovsky \ No newline at end of file diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 482ca21..06121fb 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -11,13 +11,13 @@ $ git clone git@github.com:your-username/allure-kotlin.git Then build the project (build requires JDK 1.6 or higher): ```bash -$ ./gradlew build +$ ./gradlew build -x :samples:junit4-android:testReleaseUnitTest -x :samples:junit4-android:testDebugUnitTest ``` Make your change. Add tests for your change. Make sure all the tests pass: ```bash -$ ./gradlew test +$ ./gradlew test -x :samples:junit4-android:testReleaseUnitTest -x :samples:junit4-android:testDebugUnitTest ``` Push your fork and submit a pull request. \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b2d3aa0..1555be6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,4 +18,4 @@ jobs: with: java-version: 1.8 - name: "Build" - run: ./gradlew build + run: ./gradlew build -x :samples:junit4-android:testReleaseUnitTest -x :samples:junit4-android:testDebugUnitTest diff --git a/.github/workflows/label-verify.yml b/.github/workflows/label-verify.yml new file mode 100644 index 0000000..ec0279c --- /dev/null +++ b/.github/workflows/label-verify.yml @@ -0,0 +1,13 @@ +name: "Verify type labels" + +on: + pull_request: + types: [opened, labeled, unlabeled, synchronize] + +jobs: + triage: + runs-on: ubuntu-latest + steps: + - uses: zwaldowski/match-label-action@v2 + with: + allowed: 'type:new feature, type:improvement, type:bug' \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0945670..f2ae7ff 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,7 +14,7 @@ jobs: with: java-version: 1.8 - name: "Build" - run: ./gradlew build -Pversion=${GITHUB_REF:10} + run: ./gradlew build -x :samples:junit4-android:testReleaseUnitTest -x :samples:junit4-android:testDebugUnitTest -Pversion=${GITHUB_REF:10} - name: "Publish" run: ./gradlew publish -Pversion=${GITHUB_REF:10} env: diff --git a/allure-kotlin-android/src/main/java/io/qameta/allure/android/listeners/ExternalStoragePermissionsListener.kt b/allure-kotlin-android/src/main/java/io/qameta/allure/android/listeners/ExternalStoragePermissionsListener.kt new file mode 100644 index 0000000..1500701 --- /dev/null +++ b/allure-kotlin-android/src/main/java/io/qameta/allure/android/listeners/ExternalStoragePermissionsListener.kt @@ -0,0 +1,11 @@ +package io.qameta.allure.android.listeners + +import io.qameta.allure.android.internal.requestExternalStoragePermissions +import org.junit.runner.* +import org.junit.runner.notification.* + +class ExternalStoragePermissionsListener : RunListener() { + override fun testRunStarted(description: Description?) { + requestExternalStoragePermissions() + } +} \ No newline at end of file diff --git a/allure-kotlin-android/src/main/java/io/qameta/allure/android/runners/AllureAndroidJUnitRunners.kt b/allure-kotlin-android/src/main/java/io/qameta/allure/android/runners/AllureAndroidJUnitRunners.kt index cd150e0..c5653f7 100644 --- a/allure-kotlin-android/src/main/java/io/qameta/allure/android/runners/AllureAndroidJUnitRunners.kt +++ b/allure-kotlin-android/src/main/java/io/qameta/allure/android/runners/AllureAndroidJUnitRunners.kt @@ -7,6 +7,7 @@ import androidx.test.runner.AndroidJUnitRunner import io.qameta.allure.android.AllureAndroidLifecycle import io.qameta.allure.android.internal.isDeviceTest import io.qameta.allure.android.internal.requestExternalStoragePermissions +import io.qameta.allure.android.listeners.ExternalStoragePermissionsListener import io.qameta.allure.kotlin.Allure import io.qameta.allure.kotlin.junit4.AllureJunit4 import org.junit.runner.* @@ -29,7 +30,12 @@ class AllureAndroidJUnit4(clazz: Class<*>) : Runner(), Filterable, Sortable { } private fun createListener(): RunListener? = - if (isDeviceTest()) createDeviceListener() else createRobolectricListener() + if (isDeviceTest()) { + requestExternalStoragePermissions() + createDeviceListener() + } else { + createRobolectricListener() + } /** * Creates listener for the tests running on a device. @@ -44,7 +50,6 @@ class AllureAndroidJUnit4(clazz: Class<*>) : Runner(), Filterable, Sortable { if (Allure.lifecycle == AllureAndroidLifecycle) return null Allure.lifecycle = AllureAndroidLifecycle - requestExternalStoragePermissions() return AllureJunit4(AllureAndroidLifecycle) } @@ -72,17 +77,13 @@ open class AllureAndroidJUnitRunner : AndroidJUnitRunner() { Allure.lifecycle = AllureAndroidLifecycle val listenerArg = listOfNotNull( arguments.getCharSequence("listener"), + ExternalStoragePermissionsListener::class.java.name, AllureJunit4::class.java.name ).joinToString(separator = ",") arguments.putCharSequence("listener", listenerArg) super.onCreate(arguments) } - override fun onStart() { - super.onStart() - requestExternalStoragePermissions() - } - } /** diff --git a/build.gradle.kts b/build.gradle.kts index 649fc0f..45544e7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,7 +32,8 @@ allprojects { val gradleScriptDir by extra("${rootProject.projectDir}/gradle") configure(subprojects - .filter { !it.name.contains("android") } + .filter { !it.name.contains("android") } + .filter { it.parent?.name != "samples" } ) { apply(plugin = "org.jetbrains.kotlin.jvm") apply(from = "$gradleScriptDir/maven-publish.gradle") diff --git a/samples/junit4-android/build.gradle.kts b/samples/junit4-android/build.gradle.kts new file mode 100644 index 0000000..b2af226 --- /dev/null +++ b/samples/junit4-android/build.gradle.kts @@ -0,0 +1,54 @@ +plugins { + id("com.android.application") + id("kotlin-android") +} + +android { + compileSdkVersion(Versions.Android.compileSdk) + defaultConfig { + applicationId = "io.qameta.allure.sample.junit4.android" + minSdkVersion(Versions.Android.minSdk) + targetSdkVersion(Versions.Android.targetSdk) + versionCode = 1 + versionName = version as String + + testInstrumentationRunner = "io.qameta.allure.android.runners.AllureAndroidJUnitRunner" + testInstrumentationRunnerArguments(mapOf("clearPackageData" to "true")) + } + + buildTypes { + getByName("release") { + isMinifyEnabled = false + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + } + } + + sourceSets { + val sharedTestDir = "src/sharedTest/java" + getByName("test").java.srcDir(sharedTestDir) + getByName("androidTest").java.srcDir(sharedTestDir) + } + + testOptions.unitTests.isIncludeAndroidResources = true +} + +dependencies { + implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) + implementation(kotlin("stdlib-jdk7", Versions.kotlin)) + + implementation("androidx.appcompat:appcompat:${Versions.Android.androidX}") + implementation("androidx.core:core-ktx:${Versions.Android.androidX}") + + listOf( + project(":allure-kotlin-android"), + "androidx.test.ext:junit:${Versions.Android.Test.junit}", + "androidx.test:runner:${Versions.Android.Test.runner}", + "junit:junit:${Versions.junit4}", + "androidx.test.espresso:espresso-core:${Versions.Android.Test.espresso}" + ).forEach { + testImplementation(it) + androidTestImplementation(it) + } + + testImplementation("org.robolectric:robolectric:${Versions.Android.Test.robolectric}") +} diff --git a/samples/junit4-android/proguard-rules.pro b/samples/junit4-android/proguard-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/samples/junit4-android/src/androidTest/resources/META-INF/services/io.qameta.allure.kotlin.listener.ContainerLifecycleListener b/samples/junit4-android/src/androidTest/resources/META-INF/services/io.qameta.allure.kotlin.listener.ContainerLifecycleListener new file mode 100644 index 0000000..0812f09 --- /dev/null +++ b/samples/junit4-android/src/androidTest/resources/META-INF/services/io.qameta.allure.kotlin.listener.ContainerLifecycleListener @@ -0,0 +1 @@ +io.qameta.allure.android.listeners.LogcatContainerListener \ No newline at end of file diff --git a/samples/junit4-android/src/androidTest/resources/META-INF/services/io.qameta.allure.kotlin.listener.StepLifecycleListener b/samples/junit4-android/src/androidTest/resources/META-INF/services/io.qameta.allure.kotlin.listener.StepLifecycleListener new file mode 100644 index 0000000..f5bb838 --- /dev/null +++ b/samples/junit4-android/src/androidTest/resources/META-INF/services/io.qameta.allure.kotlin.listener.StepLifecycleListener @@ -0,0 +1 @@ +io.qameta.allure.android.listeners.LogcatStepLifecycleListener \ No newline at end of file diff --git a/samples/junit4-android/src/androidTest/resources/META-INF/services/io.qameta.allure.kotlin.listener.TestLifecycleListener b/samples/junit4-android/src/androidTest/resources/META-INF/services/io.qameta.allure.kotlin.listener.TestLifecycleListener new file mode 100644 index 0000000..b228228 --- /dev/null +++ b/samples/junit4-android/src/androidTest/resources/META-INF/services/io.qameta.allure.kotlin.listener.TestLifecycleListener @@ -0,0 +1 @@ +io.qameta.allure.android.listeners.LogcatTestLifecycleListener \ No newline at end of file diff --git a/samples/junit4-android/src/androidTest/resources/allure.properties b/samples/junit4-android/src/androidTest/resources/allure.properties new file mode 100644 index 0000000..c858edb --- /dev/null +++ b/samples/junit4-android/src/androidTest/resources/allure.properties @@ -0,0 +1,2 @@ +allure.results.directory=allure-results +allure.link.issue.pattern=https://jira.domain-name.com/browse/{} diff --git a/samples/junit4-android/src/debug/AndroidManifest.xml b/samples/junit4-android/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..45daac6 --- /dev/null +++ b/samples/junit4-android/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/samples/junit4-android/src/main/AndroidManifest.xml b/samples/junit4-android/src/main/AndroidManifest.xml new file mode 100644 index 0000000..9ad841e --- /dev/null +++ b/samples/junit4-android/src/main/AndroidManifest.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/junit4-android/src/main/java/io/qameta/allure/sample/junit4/android/CrashActivity.kt b/samples/junit4-android/src/main/java/io/qameta/allure/sample/junit4/android/CrashActivity.kt new file mode 100644 index 0000000..2831033 --- /dev/null +++ b/samples/junit4-android/src/main/java/io/qameta/allure/sample/junit4/android/CrashActivity.kt @@ -0,0 +1,36 @@ +package io.qameta.allure.sample.junit4.android + +import android.os.Bundle +import android.widget.Button +import androidx.annotation.VisibleForTesting +import androidx.appcompat.app.AppCompatActivity +import java.util.concurrent.Executors +import java.util.concurrent.TimeUnit + +class CrashActivity : AppCompatActivity() { + + private val crashImmediate: Button + get() = findViewById(R.id.button_crash_immediate) + private val crashAsync: Button + get() = findViewById(R.id.button_crash_async) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_crash) + + crashImmediate.setOnClickListener { + throw IllegalStateException("Crashing on purpose!") + } + crashAsync.setOnClickListener { + Executors.newSingleThreadExecutor().execute { + Thread.sleep(ASYNC_CRASH_TIME_MS) + throw IllegalStateException("Crashing async on purpose!") + } + } + } + + companion object { + @VisibleForTesting + val ASYNC_CRASH_TIME_MS: Long = TimeUnit.SECONDS.toMillis(1) + } +} diff --git a/samples/junit4-android/src/main/java/io/qameta/allure/sample/junit4/android/SampleActivity.kt b/samples/junit4-android/src/main/java/io/qameta/allure/sample/junit4/android/SampleActivity.kt new file mode 100644 index 0000000..936e71b --- /dev/null +++ b/samples/junit4-android/src/main/java/io/qameta/allure/sample/junit4/android/SampleActivity.kt @@ -0,0 +1,19 @@ +package io.qameta.allure.sample.junit4.android + +import android.os.Bundle +import android.widget.Button +import android.widget.TextView +import androidx.appcompat.app.AppCompatActivity + +class SampleActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_sample) + + findViewById