Tree Matchers for Kotlin

A testing DSL to specify the structure of a tree in a concise and readable way.

License

License

GroupId

GroupId

com.github.oowekyala.treeutils
ArtifactId

ArtifactId

tree-matchers
Last Version

Last Version

2.1.0
Release Date

Release Date

Type

Type

jar
Description

Description

Tree Matchers for Kotlin
A testing DSL to specify the structure of a tree in a concise and readable way.
Project URL

Project URL

https://github.com/oowekyala/kt-tree-matchers
Source Code Management

Source Code Management

https://github.com/oowekyala/kt-tree-matchers

Download tree-matchers

How to add to project

<!-- https://jarcasting.com/artifacts/com.github.oowekyala.treeutils/tree-matchers/ -->
<dependency>
    <groupId>com.github.oowekyala.treeutils</groupId>
    <artifactId>tree-matchers</artifactId>
    <version>2.1.0</version>
</dependency>
// https://jarcasting.com/artifacts/com.github.oowekyala.treeutils/tree-matchers/
implementation 'com.github.oowekyala.treeutils:tree-matchers:2.1.0'
// https://jarcasting.com/artifacts/com.github.oowekyala.treeutils/tree-matchers/
implementation ("com.github.oowekyala.treeutils:tree-matchers:2.1.0")
'com.github.oowekyala.treeutils:tree-matchers:jar:2.1.0'
<dependency org="com.github.oowekyala.treeutils" name="tree-matchers" rev="2.1.0">
  <artifact name="tree-matchers" type="jar" />
</dependency>
@Grapes(
@Grab(group='com.github.oowekyala.treeutils', module='tree-matchers', version='2.1.0')
)
libraryDependencies += "com.github.oowekyala.treeutils" % "tree-matchers" % "2.1.0"
[com.github.oowekyala.treeutils/tree-matchers "2.1.0"]

Dependencies

compile (1)

Group / Artifact Type Version
com.github.oowekyala.treeutils : tree-printers jar 2.1.0

provided (2)

Group / Artifact Type Version
org.jetbrains.kotlin : kotlin-stdlib-jdk7 jar 1.3.10
org.jetbrains.kotlin : kotlin-test jar 1.3.10

Project Modules

There are no modules declared in this project.

Tree Matchers for Kotlin tests

This is a lightweight testing DSL to assert that a tree conforms to an expected structure. Its focus is to maximise readability and provide detailed error messages. It supports any tree-like structure, you just have to plug in an adapter.

Jump to the Setup section or take a look at the samples below.

Samples

node should matchNode<ASTStatement> {

    // nesting matchers allow to specify a whole subtree
    child<ASTForStatement> {

        // This would fail if the first child of the ForStatement wasn't a ForInit
        child<ASTForInit> {
            child<ASTLocalVariableDeclaration> {

                // If the parameter ignoreChildren is set to true, the number of children is not asserted
                // Calls to "child" in the block are forbidden
                // The only checks carried out here are the type test and the assertions of the block
                child<ASTType>(ignoreChildren = true) {

                    // In a "child" block, the tested node can be referred to as "it"
                    // Here, its static type is ASTType, so we can inspect properties
                    // of the node and make assertions

                    it.typeImage shouldBe "int"
                    it.type shouldNotBe null
                }

                // We don't care about that node, we only care that there is "some" node
                unspecifiedChild()
            }
        }

        // The subtree is ignored, but we check a ForUpdate is present at this child position
        child<ASTForUpdate>(ignoreChildren = true) {}

        // Here, ignoreChildren is not specified and takes its default value of false.
        // The lambda has no "child" calls and the node will be asserted to have no children
        child<ASTBlock> {}
    }
}

See also the Kotlin docs.

Setup

You need JDK 1.8+, but the libraries use your provided dependencies instead of shipping a kotlin standard library and kotlin test framework.

Maven

<dependency>
  <groupId>com.github.oowekyala.treeutils</groupId>
  <artifactId>tree-matchers</artifactId>
  <version>2.1.0</version>
</dependency>

Gradle

   implementation 'com.github.oowekyala.treeutils:tree-matchers:2.1.0'

or with the Kotlin DSL:

   implementation("com.github.oowekyala.treeutils:tree-matchers:2.1.0")

Provide an adapter

For example, if your tree type hierarchy is topped by a class named Node, you should:

  • Implement TreeLikeAdapter<Node> on some object
  • Define some shorthand methods, to avoid providing the adapter every time

Here it is in code:

object NodeTreeLikeAdapter : TreeLikeAdapter<Node> {
    override fun getChildren(node: Node): List<Node> = /* implementation */
}


typealias NodeSpec<N> = TreeNodeWrapper<Node, N>.() -> Unit

// This can be used with plain kotlin.test : someNode.shouldMatchNode<Foo> { ... }
inline fun <reified N : Node> Node?.shouldMatchNode(
                                        ignoreChildren: Boolean = false,
                                        noinline nodeSpec: NodeSpec<N>
                                    ) = this.baseShouldMatchSubtree(MatchingConfig(adapter = NodeTreeLikeAdapter), ignoreChildren, nodeSpec = nodeSpec)

// This can be used with kotlintest's "someNode should matchNode<Foo> { ... }"
inline fun <reified N : Node> matchNode(
                                    ignoreChildren: Boolean = false,
                                    noinline nodeSpec: NodeSpec<N>
                              ) : (Node?) -> Unit = { it.shouldMatchNode(ignoreChildren, nodeSpec) }

More complete documentation can be found in the Kotlin docs of the project. Happy testing!

Versions

Version
2.1.0
2.0.2
2.0.1
2.0