Skip to content
/ ktest Public

kTest - integration/acceptance/system/whatever test oriented modular test framework in Kotlin

License

Notifications You must be signed in to change notification settings

saksmt/ktest

Folders and files

NameName
Last commit message
Last commit date

Latest commit

22ba03a · Aug 10, 2018
Jun 21, 2018
Feb 5, 2018
Dec 8, 2017
Jun 21, 2018
Aug 10, 2018
Feb 6, 2018
Aug 10, 2018
Aug 10, 2018
Feb 6, 2018
May 22, 2018
Jan 22, 2018
Feb 2, 2018
Feb 5, 2018
Dec 8, 2017
Mar 3, 2018
Feb 2, 2018
Aug 10, 2018
Aug 10, 2018
Aug 10, 2018
Dec 1, 2017
Dec 1, 2017
Feb 2, 2018

Repository files navigation

kTest

CircleCI Maven metadata URI

kTest is integration / acceptance / system / any other non-unit test oriented modular test framework in Kotlin. Inspired by kotlintest, specs2 and martians.

Usage

object MyTestSpecification : BehaviorSpec({
    given("some service") {
        `when`("executing it's API") {
            then("it should work correctly") {
                // test body...
            }
        }
    }
})
fun makeMyHttp(): List<Account> {
    return rest["my-backend"] {
        using(url) {
            agreements / param("id") / accounts 
        } execute {
            GET(pathParam(123), header("Accept", "application/json"))
        }
    }
}
fun loadAccounts(resourcePath: String) =
    resourcePath.loadAsJson { list(map<String, Any>()) }.also {
        println(it.dump()) // pretty-printing pseudo-logging
    }
fun compareMyJsons(expected: JsonNode, actual: JsonNode) {
    with(JsonNodeMatchers) {
        assertThat(actual, isIdenticalTo(expected).bySubtree {
            // comparing only meaningful nodes
            "accounts[*]" {
                + "id"
                + "accountNumber"
                
                "owner" {
                    + "id"
                    + "name"
                }
            }
        })
    }
}

Powered by JSONPath

fun allIdsNearAccountNumbers(jp: DocumentContext) =
    jp select "id" where {
        "accountNumber".exists()
    } castTo { list<Long>() }
fun getAccounts(activeOn: Date) =
    "my-database".db {
        select<Account>("""
           | SELECT * FROM accounts 
           | WHERE 
           |   close_date is NULL 
           |   OR close_date < :activeOn
        """.trimMargin()) {
            parameter("activeOn", activeOn)
        }.asList()
    }
object MyTest : SimpleSpec({
    suite("my service suite") {
        restTest(name = { "${it.method} accounts" }) {
            url { agreements / accounts }
        
            GET(queryParam("name", "%"))
            POST(body("name", "%")) { it / search }
            
            expect { response: DocumentContext ->
                // do some check
            }
        }
    }
})

Reporting powered by excellent Allure

object MyTest : AllureSpec({
    feature("some feature", metaInfo = {
        blocker()
    }) {
        story("true story", metaInfo = {
            issue("PROJ-111")
        }) {
            case("my case", metaInfo = {
                description("my description")
            }) {
                // test body...
            }
        }
    }
})

Putting it all together

object AccountByCustomerRestApiSpec : AllureSpec({
    beforeAll {
        rest["backend"] {
            using(url) {
                `internal` / caches
            } execute {
                DELETE(queryParam("force", "true"))
            }
        }
    }

    epic("Search") {
        feature("Account by customer search") {
            story("Single criteria search") {
                val testTable = table(
                    header("criteriaName", "criteriaValue", "expectedJsonName"),
                    row("billing", ">100", "richAccounts.json"),
                    row("region", "Central", "centralRegionAccounts.json"),
                    row("validTill", ">${LocalDate.now().format(DateTimeFormatter.ISO_DATE)}", "activeAccounts.json")
                )
                // should be generated right before test
                val myGeneratedCustomer: Customer = testData["customer.json"]
                
                forAll(testTable) { criteriaName, criteriaValue, expectedJsonName ->
                    val criteria = mapOf<String, String>(
                        criteriaName, criteriaValue
                    )
                    
                    restTest(name = { "Search account by \"$criteriaName\": ${it.method}" }, metaData = {
                        category<Complex>()
                        flaky()
                    }) {
                        url { customers / param("customerId") / accounts }
                        
                        GET(queryParams(criteria), pathParam("customerId", myGeneratedCustomer.id))
                        POST(body(criteria), pathParam("customerId", myGeneratedCustomer.id))
                        
                        expect { response: DocumentContext ->
                            with(DocumentContextMatchers) {
                                assertThat(response, matches(expectedJsonName.loadAsJsonPath()).afterRemovalOfSubtree {
                                    "account[].metaData" {
                                        + "date"
                                        + "IP"
                                    }
                                })
                            }
                        }
                    }
                }
            }
        }
    }
})

For more see docs and samples

Download

You can use dependency management

Gradle

compile 'run.smt.ktest:ktest-api'
compile 'run.smt.ktest:ktest-config'
compile 'run.smt.ktest:ktest-util'
compile 'run.smt.ktest:ktest-runner-junit4'
compile 'run.smt.ktest:ktest-allure'
compile 'run.smt.ktest:ktest-jackson'
compile 'run.smt.ktest:ktest-json-matchers'
compile 'run.smt.ktest:ktest-jsonpath'
compile 'run.smt.ktest:ktest-db'
compile 'run.smt.ktest:ktest-rest'
compile 'run.smt.ktest:ktest-resttest'

Maven

<dependency>
    <groupId>run.smt.ktest</groupId>
    <artifactId>ktest-api</artifactId>
</dependency>

<dependency>
    <groupId>run.smt.ktest</groupId>
    <artifactId>ktest-config</artifactId>
</dependency>

<dependency>
    <groupId>run.smt.ktest</groupId>
    <artifactId>ktest-util</artifactId>
</dependency>

<dependency>
    <groupId>run.smt.ktest</groupId>
    <artifactId>ktest-runner-junit4</artifactId>
</dependency>

<dependency>
    <groupId>run.smt.ktest</groupId>
    <artifactId>ktest-allure</artifactId>
</dependency>

<dependency>
    <groupId>run.smt.ktest</groupId>
    <artifactId>ktest-jackson</artifactId>
</dependency>

<dependency>
    <groupId>run.smt.ktest</groupId>
    <artifactId>ktest-json-matchers</artifactId>
</dependency>

<dependency>
    <groupId>run.smt.ktest</groupId>
    <artifactId>ktest-jsonpath</artifactId>
</dependency>

<dependency>
    <groupId>run.smt.ktest</groupId>
    <artifactId>ktest-db</artifactId>
</dependency>

<dependency>
    <groupId>run.smt.ktest</groupId>
    <artifactId>ktest-rest</artifactId>
</dependency>

<dependency>
    <groupId>run.smt.ktest</groupId>
    <artifactId>ktest-resttest</artifactId>
</dependency>

License

All source code is licensed under MIT license