Skip to content

Commit

Permalink
test: add verification api integration tests (#1201)
Browse files Browse the repository at this point in the history
Signed-off-by: Allain Magyar <[email protected]>
Signed-off-by: Hyperledger Bot <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Hyperledger Bot <[email protected]>
  • Loading branch information
3 people authored Jun 27, 2024
1 parent 68626ed commit c05df45
Show file tree
Hide file tree
Showing 43 changed files with 1,237 additions and 526 deletions.
12 changes: 11 additions & 1 deletion .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ jobs:
runs-on: ubuntu-latest
if: ${{ !contains(github.event.pull_request.title, '[skip ci]') }}
env:
LOGS_DIR: "tests/integration-tests/target/logs"
REPORTS_DIR: "tests/integration-tests/target/site/serenity"
steps:
- name: Checkout
Expand Down Expand Up @@ -131,12 +132,21 @@ jobs:
comment_title: "Integration Test Results"
check_name: "Integration Test Results"

- name: Upload artifacts
- name: Upload serenity report
if: github.ref_name == 'main' || failure()
uses: actions/upload-artifact@v4
with:
name: integration-tests-result
path: ${{ env.REPORTS_DIR }}
compression-level: 9

- name: Upload logs
if: github.ref_name == 'main' || failure()
uses: actions/upload-artifact@v4
with:
name: docker-logs
path: ${{ env.LOGS_DIR }}
compression-level: 9

- name: Slack Notification
if: github.ref_name == 'main' && failure()
Expand Down
107 changes: 81 additions & 26 deletions tests/integration-tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ The Screenplay pattern is used to write the tests. The pattern is described in d
* Each actor has their own abilities (actions they can perform) and interactions (tasks they can carry out). These interactions encapsulate the steps required to achieve a certain goal in the system.
* The Screenplay Pattern promotes the use of high-level, business-oriented language in test scripts, making them more understandable to non-technical stakeholders.

<p align="center">
<img src="docs/static/screenplay.png" alt="Screenplay pattern overview" width="750"/><br>
<em>Pic. 1. Screenplay pattern overview</em>
<p style="text-align: center">
<picture>
<img src="docs/static/screenplay.png" alt="Screenplay pattern overview" width="750"/>
</picture><br>
<em>Screenplay pattern overview</em>
</p>

## Project structure
Expand Down Expand Up @@ -66,9 +68,11 @@ The main idea of the framework is to test the ICA as a black box.

The tests interact with the ICA through the API and webhook messages.

<p align="center">
<img src="docs/static/system_under_test.png" alt="Screenplay pattern overview" width="800"/><br>
<em>Pic. 2. Overview of the system under test. Roles, Agents and Services communication.</em>
<p style="text-align: center">
<picture>
<img src="docs/static/system_under_test.png" alt="Screenplay pattern overview" width="800"/>
</picture><br>
<em>Overview of the system under test. Roles, Agents and Services communication.</em>
</p>

### ICA Roles in Tests
Expand Down Expand Up @@ -397,7 +401,7 @@ The following variables must be set before running the tests:
* `AGENT_VERSION`: version of the ICA docker image to use.

```shell
TESTS_CONFIG=/configs/basic.conf PRISM_NODE_VERSION=2.3.0 AGENT_VERSION=1.30.1 ./gradlew test
TESTS_CONFIG=/configs/basic.conf PRISM_NODE_VERSION=2.3.0 AGENT_VERSION=1.36.1 ./gradlew test
```

> Please note: there is no need to pass environment variables if you're using already running agents.
Expand All @@ -414,17 +418,37 @@ To simplify the execution, each configuration file creates a new `gradle` task.
It's possible to execute the configuration file as

```shell
PRISM_NODE_VERSION=2.3.0 AGENT_VERSION=1.30.1 ./gradlew test_basic
PRISM_NODE_VERSION=2.3.0 AGENT_VERSION=1.36.1 ./gradlew test_basic
```

Also, it's possible to execute the integration tests to all configurations files. The task is named `regression`, it should take a lot of time to execute.

Note: report is not working due constrains in Serenity BDD reporting system.
Also, it's possible to execute the integration tests to all configurations files. The task is named `regression`, it should take a long time to execute.

```shell
PRISM_NODE_VERSION=2.3.0 AGENT_VERSION=1.30.1 ./gradlew regression
PRISM_NODE_VERSION=2.3.0 AGENT_VERSION=1.36.1 ./gradlew regression
```

#### Regression report

Running the regression tasks implies running the same features multiple times.
To enable a full report of the regression execution, `context` variable was introduced to the report.

To run all scenarios, even if there's a failure, it's required to add `--continue` to the execution

Example
```bash
AGENT_VERSION=v1.36.1 PRISM_NODE_VERSION=v2.3.0 ./gradlew regression --continue
```

Each `context` is based on the configuration used for the current execution and will be displayed in the
Serenity report:

<p style="text-align: center">
<picture>
<img src="docs/static/serenity_context.png" alt="Serenity Regression report contexts" width="800">
</picture><br>
<em>Serenity Regression report with contexts</em>
</p>

### Running scenarios in IntelliJ IDEA

To run the scenarios in IntelliJ IDEA, you need to create a new run configuration.
Expand All @@ -433,9 +457,11 @@ It is easy to do by executing `IntegrationTestsRunner` class and selecting the r

The required configuration will be created, but you have to edit it to set the environment variables.

<p align="center">
<img src="docs/static/intellij.png" alt="Running tests in IntelliJ IDEA" width="850"/><br>
<em>Pic. 3. Running tests through IntelliJ IDEA.</em>
<p style="text-align: center">
<picture>
<img src="docs/static/intellij.png" alt="Running tests in IntelliJ IDEA" width="850"/>
</picture><br>
<em>Running tests through IntelliJ IDEA.</em>
</p>

You could edit `@CucumberOptions` annotation to specify the features to run, as well as specify tags to include or exclude:
Expand All @@ -444,8 +470,9 @@ For example, here is how you can run only connection scenarios:
```kotlin
@CucumberOptions(
features = ["src/test/resources/features/connection"],
...
// ...
)
class IntegrationTestsRunner
```

If you would like to run only particular scenarios from the feature or combine multiple scenarios from different feature file,
Expand All @@ -454,8 +481,9 @@ you could use tags:
@CucumberOptions(
features = ["src/test/resources/features"],
tags = ["@connection and @credentials"],
...
// ...
)
class IntegrationTestsRunner
```

> Please note: if you use custom tags, you need to specify them in the feature files as well.
Expand Down Expand Up @@ -488,21 +516,27 @@ You could start by opening `index.html` file in your browser.

On the main report page you could see the summary of the test run as well as the functional coverage table:

<p align="center">
<img src="docs/static/report_summary.png" alt="Report summary" width="800"/><br>
<em>Pic. 4. HTML-report summary example.</em>
<p style="text-align: center">
<picture>
<img src="docs/static/report_summary.png" alt="Report summary" width="800"/>
</picture><br>
<em>HTML-report summary example.</em>
</p>

<p align="center">
<img src="docs/static/functional_coverage.png" alt="Functional coverage" width="800"/><br>
<em>Pic. 5. Functional coverage example.</em>
<p style="text-align: center">
<picture>
<img src="docs/static/functional_coverage.png" alt="Functional coverage" width="800"/>
</picture><br>
<em>Functional coverage example.</em>
</p>

Then, you can go deeper to each scenario and open each step to see the details of the test execution:

<p align="center">
<img src="docs/static/rest_requests.png" alt="REST requests analysis" width="800"/><br>
<em>Pic. 6. REST requests analysis example.</em>
<p style="text-align: center">
<picture>
<img src="docs/static/rest_requests.png" alt="REST requests analysis" width="800"/>
</picture><br>
<em>REST requests analysis example.</em>
</p>

### Summary reports
Expand Down Expand Up @@ -530,3 +564,24 @@ And summary reports themselves will be available in `./target/site/serenity` fol
JUnit XML reports are also generated under `./target/site/serenity` folder with names `SERENITY-JUNIT-*.xml`.

> For more information about the reports, please refer to [Serenity BDD reports documentation](https://serenity-bdd.github.io/docs/reporting/the_serenity_reports).

### Docker logs

Docker logs are now redirected to `target/logs` folder.

If you're running the test using the custom config goals it will have the context added
to the path as `target/logs/basic`.

Example
```bash
AGENT_VERSION=v1.36.1 PRISM_NODE_VERSION=v2.3.0 ./gradlew test_basic
```

Will have the logs output as such:

<p style="text-align: center">
<picture>
<img src="docs/static/logs.png" alt="Docker logs directory" width="346"/>
</picture><br>
<em>Docker logs directory</em>
</p>
16 changes: 11 additions & 5 deletions tests/integration-tests/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ version = "1.0-SNAPSHOT"

buildscript {
dependencies {
classpath("net.serenity-bdd:serenity-single-page-report:4.1.4")
classpath("net.serenity-bdd:serenity-json-summary-report:4.1.4")
classpath("net.serenity-bdd:serenity-single-page-report:4.0.46")
classpath("net.serenity-bdd:serenity-json-summary-report:4.0.46")
}
}

Expand All @@ -33,14 +33,18 @@ dependencies {
testImplementation("io.ktor:ktor-server-netty:2.3.0")
testImplementation("io.ktor:ktor-client-apache:2.3.0")
// RestAPI client
testImplementation("org.hyperledger.identus:cloud-agent-client-kotlin:1.33.1")
testImplementation("org.hyperledger.identus:cloud-agent-client-kotlin:1.36.1")
// Test helpers library
testImplementation("io.iohk.atala:atala-automation:0.4.0")
// Hoplite for configuration
testImplementation("com.sksamuel.hoplite:hoplite-core:2.7.5")
testImplementation("com.sksamuel.hoplite:hoplite-hocon:2.7.5")
// Kotlin compose
testImplementation("org.testcontainers:testcontainers:1.19.1")
// Crypto
testImplementation("com.nimbusds:nimbus-jose-jwt:9.40")
testImplementation("org.bouncycastle:bcprov-jdk18on:1.78.1")
testImplementation("com.google.crypto.tink:tink:1.13.0")
}

serenity {
Expand All @@ -54,7 +58,7 @@ tasks.register<Delete>("cleanTarget") {

tasks.test {
dependsOn("cleanTarget")
finalizedBy("reports")
finalizedBy("aggregate", "reports")
testLogging.showStandardStreams = true
systemProperty("cucumber.filter.tags", System.getProperty("cucumber.filter.tags"))
}
Expand Down Expand Up @@ -82,19 +86,21 @@ afterEvaluate {
tasks.register<Test>("test_$fileName") {
group = "verification"
testLogging.showStandardStreams = true
systemProperty("context", fileName)
systemProperty("TESTS_CONFIG", "/configs/$fileName.conf")
systemProperty("PRISM_NODE_VERSION", System.getenv("PRISM_NODE_VERSION") ?: "")
systemProperty("AGENT_VERSION", System.getenv("AGENT_VERSION") ?: "")
systemProperty("cucumber.filter.tags", System.getProperty("cucumber.filter.tags"))
finalizedBy("aggregate", "reports")
outputs.upToDateWhen { false }
}
}

/**
* Runs the integration suite for each config file present
* Restrictions: aggregation of all executions doesn't work because of serenity configuration
*/
tasks.register("regression") {
tasks.register<Test>("regression") {
dependsOn("cleanTarget")
group = "verification"
configFiles.forEach {
Expand Down
Binary file added tests/integration-tests/docs/static/logs.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion tests/integration-tests/serenity.properties
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
serenity.project.name=Open Enterprise Agent Integration tests
serenity.project.name=Identus Integration tests
jira.url=https://input-output.atlassian.net
jira.project=ATL
serenity.reports.show.step.details=true
serenity.report.show.manual.tests=false
serenity.verbose.steps=true
serenity.simplified.stack.traces=false
serenity.report.accessibility=true
json.pretty.printing=true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,15 @@ enum class CredentialSchema {
tags = listOf("school", "students"),
version = "1.0.0",
)
override val claims: Map<String, Any> = linkedMapOf(
"name" to "Name",
"age" to 18,
)
}, ;

abstract val credentialSchema: CredentialSchemaInput
abstract val schema: JsonSchema
abstract val credentialSchemaType: String
abstract val schemaType: String
abstract val claims: Map<String, Any>
}
25 changes: 25 additions & 0 deletions tests/integration-tests/src/test/kotlin/common/DidPurpose.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package common

import org.hyperledger.identus.client.models.*

enum class DidPurpose {
EMPTY {
override val publicKeys = emptyList<ManagedDIDKeyTemplate>()
override val services = emptyList<Service>()
},
JWT {
override val publicKeys = listOf(
ManagedDIDKeyTemplate("auth-1", Purpose.AUTHENTICATION, Curve.SECP256K1),
ManagedDIDKeyTemplate("auth-2", Purpose.AUTHENTICATION, Curve.ED25519),
ManagedDIDKeyTemplate("assertion-1", Purpose.ASSERTION_METHOD, Curve.SECP256K1),
)
override val services = emptyList<Service>()
},
ANONCRED {
override val publicKeys = emptyList<ManagedDIDKeyTemplate>()
override val services = emptyList<Service>()
}, ;

abstract val publicKeys: List<ManagedDIDKeyTemplate>
abstract val services: List<Service>
}
Loading

0 comments on commit c05df45

Please sign in to comment.