Testing Guidelines

This guide outlines testing guidelines and best practices for TrustWeave.

Overview

TrustWeave testing strategy includes:

  • Unit Tests – test individual components in isolation
  • Integration Tests – test component interactions
  • End-to-End Tests – test complete workflows
  • Test Utilitiestrustweave-testkit for in-memory implementations

Testing Principles

Test Isolation

Each test should be independent:

1
2
3
4
5
6
7
@Test
fun testIsolated() = runBlocking {
    // Each test gets its own fixture
    val fixture = TrustWeaveTestFixture.builder().build().use { fixture ->
        // Test code
    }
}

Test Naming

Use descriptive test names:

1
2
3
4
@Test
fun testCreateDidWithEd25519Algorithm() = runBlocking {
    // ...
}

Test Organization

Organize tests by functionality:

1
2
3
4
5
6
7
8
9
10
11
class DidMethodTest {
    @Test
    fun testCreateDid() = runBlocking {
        // ...
    }

    @Test
    fun testResolveDid() = runBlocking {
        // ...
    }
}

Unit Testing

Testing DID Methods

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import org.trustweave.testkit.*
import org.trustweave.did.*
import kotlin.test.Test
import kotlin.test.assertNotNull

class DidMethodTest {
    @Test
    fun testCreateDid() = runBlocking {
        val kms = InMemoryKeyManagementService()
        val method = DidKeyMockMethod(kms)

        val options = didCreationOptions {
            algorithm = KeyAlgorithm.Ed25519
        }

        val did = method.createDid(options)
        assertNotNull(did)
        assert(did.id.startsWith("did:key:"))
    }
}

Testing Key Management

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import org.trustweave.testkit.kms.InMemoryKeyManagementService
import org.trustweave.kms.*
import kotlin.test.Test

class KmsTest {
    @Test
    fun testGenerateAndSign() = runBlocking {
        val kms = InMemoryKeyManagementService()

        val key = kms.generateKey(Algorithm.Ed25519)
        assertNotNull(key)

        val data = "Hello, TrustWeave!".toByteArray()
        val signature = kms.sign(key.id, data)

        assertNotNull(signature)
        assertEquals(64, signature.size) // Ed25519 signature size
    }
}

Integration Testing

Testing Credential Workflows

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import org.trustweave.testkit.*
import org.trustweave.TrustWeave
import kotlin.test.Test

class CredentialWorkflowTest {
    @Test
    fun testCredentialIssuanceAndVerification() = runBlocking {
        val fixture = TrustWeaveTestFixture.builder()
            .withInMemoryBlockchainClient("algorand:testnet")
            .build()
            .use { fixture ->
                val TrustWeave = TrustWeave.create()

                // Create issuer DID
                val issuerDid = TrustWeave.createDid().getOrThrow()

                // Issue credential
                val credential = TrustWeave.issueCredential(
                    issuerDid = issuerDid.id,
                    issuerKeyId = issuerDid.document.verificationMethod.first().id,
                    credentialSubject = buildJsonObject {
                        put("id", "did:key:subject")
                        put("name", "Alice")
                    }
                ).getOrThrow()

                // Verify credential
                val verificationResult = TrustWeave.verifyCredential(credential).getOrThrow()
                assert(verificationResult.valid)
            }
    }
}

End-to-End Testing

EO Integration Tests

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import org.trustweave.testkit.eo.BaseEoIntegrationTest
import org.trustweave.testkit.anchor.InMemoryBlockchainAnchorClient
import org.trustweave.anchor.*
import kotlin.test.Test

class MyEoIntegrationTest : BaseEoIntegrationTest() {
    override fun createAnchorClient(
        chainId: String,
        options: Map<String, Any?>
    ): BlockchainAnchorClient {
        return InMemoryBlockchainAnchorClient(chainId)
    }

    @Test
    fun testEoScenario() = runBlocking {
        val result = runEoTestScenario()
        assert(result.verificationResult.valid)
    }
}

Test Utilities

TrustWeaveTestFixture

Use test fixtures for setup:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import org.trustweave.testkit.*
import kotlin.test.Test

class FixtureTest {
    @Test
    fun testWithFixture() = runBlocking {
        val fixture = TrustWeaveTestFixture.builder()
            .withKms(InMemoryKeyManagementService())
            .withDidmethod(KEY) { DidKeyMockMethod(it) }
            .withBlockchainClient("algorand:testnet") {
                InMemoryBlockchainAnchorClient("algorand:testnet")
            }
            .build()
            .use { fixture ->
                val issuerDoc = fixture.createIssuerDid()
                assertNotNull(issuerDoc)
            }
    }
}

Error Testing

Testing Error Cases

1
2
3
4
5
6
7
8
9
10
11
12
@Test
fun testErrorHandling() = runBlocking {
    val kms = InMemoryKeyManagementService()

    val result = kms.sign("nonexistent-key", "data".toByteArray())
    result.fold(
        onSuccess = { fail("Expected error") },
        onFailure = { error ->
            assert(error is TrustWeaveError.KeyNotFound)
        }
    )
}

Testing Validation

1
2
3
4
5
6
7
8
9
10
11
12
@Test
fun testInvalidInput() = runBlocking {
    val method = DidKeyMockMethod(InMemoryKeyManagementService())

    val result = method.resolveDid("invalid-did")
    result.fold(
        onSuccess = { fail("Expected error") },
        onFailure = { error ->
            assert(error is TrustWeaveError.DidResolutionFailed)
        }
    )
}

Best Practices

Resource Cleanup

Always use use {} for cleanup:

1
2
3
4
fixture.use { fixture ->
    // Test code
    // Automatic cleanup on exit
}

Test Data

Use meaningful test data:

1
2
val issuerDid = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
val subjectDid = "did:key:z6MkhbXBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"

Assertions

Use descriptive assertions:

1
2
3
4
5
6
7
// Good
assertNotNull(did, "DID should not be null")
assertEquals("did:key:", did.id.substring(0, 8), "DID should start with did:key:")

// Less clear
assert(did != null)
assert(did.id.startsWith("did:key:"))

Test Coverage

Coverage Goals

Aim for:

  • Unit Tests – 80%+ coverage
  • Integration Tests – cover critical paths
  • End-to-End Tests – cover main workflows

Measuring Coverage

1
./gradlew test jacocoTestReport

Running Tests

All Tests

1
./gradlew test

Specific Module

1
./gradlew :common:test

Specific Test Class

1
./gradlew :common:test --tests "DidMethodTest"

With Verbose Output

1
./gradlew test --info

Next Steps

References


This site uses Just the Docs, a documentation theme for Jekyll.