Skip to content

Instantly share code, notes, and snippets.

@sebnozzi
Last active August 29, 2015 14:13
Show Gist options
  • Save sebnozzi/ac59b49b2946a25abdd3 to your computer and use it in GitHub Desktop.
Save sebnozzi/ac59b49b2946a25abdd3 to your computer and use it in GitHub Desktop.
package org.scalavienna.refactoringdojo.gameoflife
import org.scalatest.FunSuite
import org.scalatest.Matchers
import org.scalatest.exceptions.TestFailedException
import scala.Array.canBuildFrom
import scala.Array.fallbackCanBuildFrom
/**
* As a general rule, don't remove test-cases. You are free to add, though.
* However, consider these as acceptance tests. No need to be exhaustive here.
*
* Rely on your own unit-tests for in-depth coverage of your components.
* */
class AcceptanceTests extends FunSuite with Matchers with AcceptanceTester {
test("An isolated cell dies") {
assertGoL(
in = """ ....
.O..
....
....""",
exp = """....
....
....
....""")
}
test("A cell with only 1 neighbour dies") {
assertGoL(
in = """ ....
.O..
.O..
....""",
exp = """....
....
....
....""")
}
test("A cell with 2 neighbours lives") {
assertGoL(
in = """ O...
.O..
..O.
....""",
exp = """....
.O..
....
....""")
}
test("Acceptance test (covers all rules)") {
assertGoL(
in = """ O...
.O..
O.O.
....""",
exp = """....
OO..
.O..
....""")
}
}
/**
* You may only change the *implementation* of the "calculate"
* method, NOT the type signature. Don't add methods here.
*/
trait TestGameCalculator {
/**
* This method is the bridge between the input
* of the acceptance-tests and your real implementation
* of the game-of-life algorithm.
*
* You may change the code inside this method (you
* will actually have to). But leave the signature as-is.
*
* Try to keep this method as anemic as possible,
* delegating as much as possible to your own
* components.
*
* Ideally, it should consist of just one or two lines.
* */
def calculate(in: String): String = {
val world = new GoL()
world.from_string ( in )
world.calcNxtIter
world.to_str
}
}
/**
* You should not need to change anything here.
* Try to leave this trait as-is. It's an implementation detail.
* Ignore it.
* */
trait AcceptanceTester extends TestGameCalculator { self: FunSuite with Matchers =>
private def parse(str: String): Seq[String] = {
str.split("\n").map(_.trim())
}
def assertGoL(in: String, exp: String): Unit = {
val out = calculate(in)
if (parse(exp) != parse(out)) {
def adjust(str: String) = str.split("\n").map(s => s"\t\t${s.trim()}").mkString("\n")
val adjustedIn = adjust(in)
val adjustedExp = adjust(exp)
val adjustedOut = adjust(out)
val msg = s"""Result did not match expectation:
|Input:
|${adjustedIn}
|Expected:
|${adjustedExp}
|Got:
|${adjustedOut}""".stripMargin
throw new TestFailedException(msg, 4)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment