Invoke CLIs from Scala. Ensure they return what you Expect.
Clone or download
Latest commit 0f81f42 Aug 22, 2017

README.md

Scala Expect

Maven Central Dependency Status Reference Status Build Status Codacy Badge Codacy Badge Scaladoc license

A Scala implementation of a very small subset of the widely known TCL expect.

Scala Expect comes with three different flavors: core, fluent and dsl.

Install

libraryDependencies += "work.martins.simon" %% "scala-expect" % "6.0.0"

Core

Documentation

Advantages

  • Closer to metal / basis for the other flavors.
  • Immutable and therefore thread-safe.
  • Most errors will be caught at compile time (eg. you won't be able to use a SendWithRegex inside a StringWhen).

Disadvantages

  • Verbose syntax.
  • Can't cleanly add expect blocks/whens/actions based on a condition.

Example

import work.martins.simon.core._
import scala.concurrent.ExecutionContext.Implicits.global

val e = new Expect("bc -i", defaultValue = 5)(
  ExpectBlock(
    StringWhen("For details type `warranty'.")(
      Sendln("1 + 2")
    )
  ),
  ExpectBlock(
    RegexWhen("""\n(\d+)\n""".r)(
      SendlnWithRegex { m =>
        val previousAnswer = m.group(1)
        println(s"Got $previousAnswer")
        s"$previousAnswer + 3"
      }
    )
  ),
  ExpectBlock(
	RegexWhen("""\n(\d+)\n""".r)(
	  ReturningWithRegex(_.group(1).toInt)
	)
  )
)
e.run() //Returns 6 inside a Future[Int]

Fluent

Documentation

Advantages

  • Less verbose syntax:
    • StringWhen, RegexWhen, etc is just when.
    • Returning, ReturningWithRegex, etc is just returning.
    • Less commas and parenthesis.
  • Most errors will be caught at compile time.
  • Easy to add expect blocks/whens/actions based on a condition.
  • Easy to refactor the creation of expects.
  • Can be called from Java easily.

Disadvantages

  • Some overhead since the fluent expect is just a builder for a core expect.
  • Mutable - the fluent expect has to maintain a state of the objects that have been built.
  • IDE's will easily mess the custom indentation.

Example

import work.martins.simon.fluent._
import scala.concurrent.ExecutionContext.Implicits.global

val e = new Expect("bc -i", defaultValue = 5) {
  expect
    .when("For details type `warranty'.")
      .sendln("1 + 2")
  expect
    .when("""\n(\d+)\n""".r)
      .sendln { m =>
        val previousAnswer = m.group(1)
        println(s"Got $previousAnswer")
        s"$previousAnswer + 3"
      }
  //This is a shortcut. It works just like the previous expect block.
  expect("""\n(\d+)\n""".r)
    .returning(_.group(1).toInt)
}
e.run() //Returns 6 inside a Future[Int]

DSL

Documentation

Advantages

  • Code will be indented in blocks so IDE's won't mess the indentation.
  • Syntax more close to the TCL expect.
  • Easy to add expect blocks/whens/actions based on a condition.
  • Easy to refactor the creation of expects.

Disadvantages

  • Most errors will only be caught at runtime as opposed to compile time.
  • More overhead than the fluent expect since it's just a wrapper arround fluent expect.
  • Mutable - it uses a fluent expect as the backing expect and a mutable stack to keep track of the current context.

Example

import work.martins.simon.dsl._
import scala.concurrent.ExecutionContext.Implicits.global

val e = new Expect("bc -i", defaultValue = 5) {
  expect {
    when("For details type `warranty'.") {
      sendln("1 + 2")
    }
  }
  expect {
    when("""\n(\d+)\n""".r) {
      sendln { m =>
        val previousAnswer = m.group(1)
        println(s"Got $previousAnswer")
        s"$previousAnswer + 3"
      }
    }
  }
  //This is a shortcut. It works just like the previous expect block.
  expect("""\n(\d+)\n""".r) {
    returning(_.group(1).toInt)
  }
}
e.run() //Returns 6 inside a Future[Int]

License

Scala Expect is open source and available under the MIT license.