trackler 2.2.1.36 → 2.2.1.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/tracks/bash/config.json +1 -0
- data/tracks/ecmascript/README.md +2 -2
- data/tracks/haskell/config/maintainers.json +2 -2
- data/tracks/java/config.json +15 -3
- data/tracks/java/exercises/difference-of-squares/src/test/java/DifferenceOfSquaresCalculatorTest.java +9 -9
- data/tracks/ruby/exercises/palindrome-products/README.md +12 -6
- data/tracks/ruby/exercises/space-age/.meta/generator/test_template.erb +1 -1
- data/tracks/ruby/lib/generator/template_values.rb +6 -0
- data/tracks/ruby/lib/generator/test_template.erb +1 -1
- data/tracks/ruby/test/generator/template_values_test.rb +3 -3
- data/tracks/rust/exercises/accumulate/.gitignore +7 -0
- data/tracks/rust/exercises/clock/.gitignore +7 -0
- data/tracks/rust/exercises/nth-prime/.gitignore +7 -0
- data/tracks/rust/exercises/pig-latin/.gitignore +7 -0
- data/tracks/rust/exercises/prime-factors/.gitignore +7 -0
- data/tracks/rust/exercises/proverb/.gitignore +7 -0
- data/tracks/rust/exercises/pythagorean-triplet/.gitignore +7 -0
- data/tracks/rust/exercises/run-length-encoding/.gitignore +7 -0
- data/tracks/rust/exercises/say/.gitignore +7 -0
- data/tracks/scala/config.json +1 -0
- data/tracks/scala/exercises/clock/src/test/scala/ClockTest.scala +73 -79
- data/tracks/scala/exercises/forth/src/test/scala/ForthTest.scala +128 -133
- data/tracks/scala/exercises/kindergarten-garden/example.scala +1 -1
- data/tracks/scala/exercises/kindergarten-garden/src/test/scala/GardenTest.scala +77 -52
- data/tracks/scala/exercises/nucleotide-count/src/main/scala/.keep +0 -0
- data/tracks/scala/exercises/nucleotide-count/src/test/scala/NucleotideCountTest.scala +21 -61
- data/tracks/scala/exercises/palindrome-products/example.scala +7 -4
- data/tracks/scala/exercises/palindrome-products/src/test/scala/PalindromeProductsTest.scala +54 -34
- data/tracks/scala/testgen/src/main/scala/ClockTestGenerator.scala +66 -0
- data/tracks/scala/testgen/src/main/scala/ForthTestGenerator.scala +66 -0
- data/tracks/scala/testgen/src/main/scala/KindergartenGardenTestGenerator.scala +48 -0
- data/tracks/scala/testgen/src/main/scala/NucleotideCountTestGenerator.scala +34 -0
- data/tracks/scala/testgen/src/main/scala/PalindromeProductsTestGenerator.scala +50 -0
- data/tracks/scala/testgen/src/main/scala/testgen/CanonicalDataParser.scala +7 -6
- data/tracks/sml/config.json +21 -0
- data/tracks/sml/exercises/phone-number/README.md +64 -0
- data/tracks/sml/exercises/phone-number/example.sml +18 -0
- data/tracks/sml/exercises/phone-number/phone-number.sml +2 -0
- data/tracks/sml/exercises/phone-number/test.sml +50 -0
- data/tracks/sml/exercises/phone-number/testlib.sml +159 -0
- data/tracks/sml/exercises/roman-numerals/README.md +79 -0
- data/tracks/sml/exercises/roman-numerals/example.sml +27 -0
- data/tracks/sml/exercises/roman-numerals/roman-numerals.sml +2 -0
- data/tracks/sml/exercises/roman-numerals/test.sml +66 -0
- data/tracks/sml/exercises/roman-numerals/testlib.sml +159 -0
- metadata +26 -3
- data/tracks/scala/exercises/nucleotide-count/src/main/scala/DNA.scala +0 -6
|
File without changes
|
|
@@ -1,74 +1,34 @@
|
|
|
1
|
-
import org.scalatest.
|
|
1
|
+
import org.scalatest.{Matchers, FunSuite}
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
/** @version 1.0.0 */
|
|
4
|
+
class NucleotideCountTest extends FunSuite with Matchers {
|
|
5
5
|
|
|
6
|
-
it should "have no adenine for an empty dna string" in {
|
|
7
|
-
new DNA("").count('A') should be (Right(0))
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
it should "count cytosine for a repetitive sequence" in {
|
|
11
|
-
pending
|
|
12
|
-
new DNA("CCCCC").count('C') should be (Right(5))
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
it should "count only thymine for a mixed dna string" in {
|
|
16
|
-
pending
|
|
17
|
-
new DNA("GGGGGTAACCCGG").count('T') should be (Right(1))
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
it should "validate nucleotides" in {
|
|
21
|
-
pending
|
|
22
|
-
new DNA("GACT").count('X') should be (Left("invalid nucleotide 'X'"))
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
it should "validate dna" in {
|
|
26
|
-
pending
|
|
27
|
-
new DNA("GACYT").count('G') should be (Left("invalid nucleotide 'Y'"))
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
behavior of "nucleotideCounts"
|
|
31
6
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
7
|
+
test("empty strand") {
|
|
8
|
+
new DNA("").nucleotideCounts should be (Right(Map('A' -> 0,
|
|
9
|
+
'C' -> 0,
|
|
10
|
+
'G' -> 0,
|
|
11
|
+
'T' -> 0)))
|
|
36
12
|
}
|
|
37
13
|
|
|
38
|
-
|
|
14
|
+
test("strand with repeated nucleotide") {
|
|
39
15
|
pending
|
|
40
|
-
|
|
41
|
-
|
|
16
|
+
new DNA("GGGGGGG").nucleotideCounts should be (Right(Map('A' -> 0,
|
|
17
|
+
'C' -> 0,
|
|
18
|
+
'G' -> 7,
|
|
19
|
+
'T' -> 0)))
|
|
42
20
|
}
|
|
43
21
|
|
|
44
|
-
|
|
22
|
+
test("strand with multiple nucleotides") {
|
|
45
23
|
pending
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
24
|
+
new DNA("AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGC").nucleotideCounts should be (Right(Map('A' -> 20,
|
|
25
|
+
'C' -> 12,
|
|
26
|
+
'G' -> 17,
|
|
27
|
+
'T' -> 21)))
|
|
50
28
|
}
|
|
51
29
|
|
|
52
|
-
|
|
30
|
+
test("strand with invalid nucleotides") {
|
|
53
31
|
pending
|
|
54
|
-
|
|
55
|
-
val counts = dna.nucleotideCounts.right.get
|
|
56
|
-
counts('A')
|
|
57
|
-
val expected = Right(Map('A' -> 3, 'T' -> 2, 'C' -> 1, 'G' -> 1))
|
|
58
|
-
dna.nucleotideCounts should be (expected)
|
|
32
|
+
new DNA("AGXXACT").nucleotideCounts.isLeft should be (true)
|
|
59
33
|
}
|
|
60
|
-
|
|
61
|
-
it should "count all nucleotides" in {
|
|
62
|
-
pending
|
|
63
|
-
val s = "AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGC"
|
|
64
|
-
val dna = new DNA(s)
|
|
65
|
-
val expected = Right(Map('A' -> 20, 'T' -> 21, 'G' -> 17, 'C' -> 12))
|
|
66
|
-
dna.nucleotideCounts should be (expected)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
it should "validate dna" in {
|
|
70
|
-
pending
|
|
71
|
-
new DNA("GACYT").nucleotideCounts should be (Left("invalid nucleotide 'Y'"))
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
34
|
+
}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
|
|
2
2
|
case class PalindromeProducts(minFactor: Int, maxFactor: Int) {
|
|
3
3
|
|
|
4
|
-
lazy val (smallest: (Int, Set[(Int, Int)]),
|
|
5
|
-
largest: (Int, Set[(Int, Int)])) = {
|
|
4
|
+
lazy val (smallest: Option[(Int, Set[(Int, Int)])],
|
|
5
|
+
largest: Option[(Int, Set[(Int, Int)])]) = {
|
|
6
6
|
val palindromes = for (a <- Range(minFactor, maxFactor + 1);
|
|
7
|
-
|
|
7
|
+
b <- Range(a, maxFactor + 1) if isPalindrome(a * b)) yield (a * b, (a, b))
|
|
8
8
|
val mapped = palindromes.groupBy(_._1).map{case(k, v) => (k, v.map(_._2).toSet)}
|
|
9
|
-
(mapped.
|
|
9
|
+
if (mapped.isEmpty)
|
|
10
|
+
(None, None)
|
|
11
|
+
else
|
|
12
|
+
(Some(mapped.minBy(_._1)), Some(mapped.maxBy(_._1)))
|
|
10
13
|
}
|
|
11
14
|
|
|
12
15
|
private def isPalindrome(i: Int) = i.toString == i.toString.reverse
|
|
@@ -1,59 +1,79 @@
|
|
|
1
|
-
import org.scalatest.{Matchers,
|
|
1
|
+
import org.scalatest.{Matchers, FunSuite}
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/** @version 1.0.0 */
|
|
4
|
+
class PalindromeProductsTest extends FunSuite with Matchers {
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
// PalindromeProducts largest call is expecting a return type of
|
|
7
|
+
// Option[(Int, Set[(Int, Int)])] - None is expected for error cases.
|
|
8
|
+
// Some is expected for valid cases. The first element of the tuple
|
|
9
|
+
// is the largest palindrome product value. The second element of the
|
|
10
|
+
// tuple is the list of factors.
|
|
11
|
+
// PalindromeProducts smallest call is expecting a return type of
|
|
12
|
+
// Option[(Int, Set[(Int, Int)])] - None is expected for error cases.
|
|
13
|
+
// Some is expected for valid cases. The first element of the tuple
|
|
14
|
+
// is the smallest palindrome product value. The second element of the
|
|
15
|
+
// tuple is the list of factors.
|
|
16
|
+
|
|
17
|
+
test("finds the smallest palindrome from single digit factors") {
|
|
18
|
+
PalindromeProducts(1, 9).smallest should be(Some((1, Set((1, 1)))))
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
test("finds the largest palindrome from single digit factors") {
|
|
22
|
+
pending
|
|
23
|
+
PalindromeProducts(1, 9).largest should be(Some((9, Set((1, 9), (3, 3)))))
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
test("find the smallest palindrome from double digit factors") {
|
|
27
|
+
pending
|
|
28
|
+
PalindromeProducts(10, 99).smallest should be(Some((121, Set((11, 11)))))
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
test("find the largest palindrome from double digit factors") {
|
|
32
|
+
pending
|
|
33
|
+
PalindromeProducts(10, 99).largest should be(Some((9009, Set((91, 99)))))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
test("find smallest palindrome from triple digit factors") {
|
|
37
|
+
pending
|
|
38
|
+
PalindromeProducts(100, 999).smallest should be(
|
|
39
|
+
Some((10201, Set((101, 101)))))
|
|
9
40
|
}
|
|
10
41
|
|
|
11
|
-
|
|
42
|
+
test("find the largest palindrome from triple digit factors") {
|
|
12
43
|
pending
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
factors should be (Set((1, 9), (3, 3)))
|
|
44
|
+
PalindromeProducts(100, 999).largest should be(
|
|
45
|
+
Some((906609, Set((913, 993)))))
|
|
16
46
|
}
|
|
17
47
|
|
|
18
|
-
|
|
48
|
+
test("find smallest palindrome from four digit factors") {
|
|
19
49
|
pending
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
factors should be (Set((11, 11)))
|
|
50
|
+
PalindromeProducts(1000, 9999).smallest should be(
|
|
51
|
+
Some((1002001, Set((1001, 1001)))))
|
|
23
52
|
}
|
|
24
53
|
|
|
25
|
-
|
|
54
|
+
test("find the largest palindrome from four digit factors") {
|
|
26
55
|
pending
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
factors should be (Set((91, 99)))
|
|
56
|
+
PalindromeProducts(1000, 9999).largest should be(
|
|
57
|
+
Some((99000099, Set((9901, 9999)))))
|
|
30
58
|
}
|
|
31
59
|
|
|
32
|
-
|
|
60
|
+
test("empty result for smallest if no palindrome in the range") {
|
|
33
61
|
pending
|
|
34
|
-
|
|
35
|
-
value should be (10201)
|
|
36
|
-
factors should be (Set((101, 101)))
|
|
62
|
+
PalindromeProducts(1002, 1003).smallest should be(None)
|
|
37
63
|
}
|
|
38
64
|
|
|
39
|
-
|
|
65
|
+
test("empty result for largest if no palindrome in the range") {
|
|
40
66
|
pending
|
|
41
|
-
|
|
42
|
-
value should be (906609)
|
|
43
|
-
factors should be (Set((913, 993)))
|
|
67
|
+
PalindromeProducts(15, 15).largest should be(None)
|
|
44
68
|
}
|
|
45
69
|
|
|
46
|
-
|
|
70
|
+
test("error result for smallest if min is more than max") {
|
|
47
71
|
pending
|
|
48
|
-
|
|
49
|
-
value should be (1002001)
|
|
50
|
-
factors should be (Set((1001, 1001)))
|
|
72
|
+
PalindromeProducts(10000, 1).smallest should be(None)
|
|
51
73
|
}
|
|
52
74
|
|
|
53
|
-
|
|
75
|
+
test("error result for largest if min is more than max") {
|
|
54
76
|
pending
|
|
55
|
-
|
|
56
|
-
value should be (99000099)
|
|
57
|
-
factors should be (Set((9901, 9999)))
|
|
77
|
+
PalindromeProducts(2, 1).largest should be(None)
|
|
58
78
|
}
|
|
59
79
|
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import java.io.File
|
|
2
|
+
|
|
3
|
+
import testgen.TestSuiteBuilder.{toString, _}
|
|
4
|
+
import testgen._
|
|
5
|
+
|
|
6
|
+
object ClockTestGenerator {
|
|
7
|
+
private def toString(expected: CanonicalDataParser.Expected): String =
|
|
8
|
+
expected.fold(_ => "", TestSuiteBuilder.toString)
|
|
9
|
+
|
|
10
|
+
private def expectedToClockStr(expected: CanonicalDataParser.Expected): String =
|
|
11
|
+
expected.fold(_ => "", any => any match {
|
|
12
|
+
case str: String => str.split(':').map(_.toInt).mkString(", ")
|
|
13
|
+
case _ => throw new IllegalArgumentException
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
private def toOperation(addArg: String): String =
|
|
17
|
+
if (addArg.startsWith("-")) "-" else "+"
|
|
18
|
+
|
|
19
|
+
def mapArgToStringForEqual(arg: Any): String = {
|
|
20
|
+
arg match {
|
|
21
|
+
case vals: Map[String, String] => s"${vals("hour")}, ${vals("minute")}"
|
|
22
|
+
case _ => throw new IllegalArgumentException
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
def sutArgsForEqual(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String =
|
|
27
|
+
argNames map (name => mapArgToStringForEqual(parseResult(name))) mkString
|
|
28
|
+
|
|
29
|
+
def fromLabeledTestAlt(propArgs: (String, Seq[String])*): ToTestCaseData =
|
|
30
|
+
withLabeledTest { sut => labeledTest =>
|
|
31
|
+
val sutFunction = labeledTest.property
|
|
32
|
+
val args = sutArgsAlt(labeledTest.result, propArgs:_*)
|
|
33
|
+
|
|
34
|
+
val sutCall =
|
|
35
|
+
if (sutFunction.toString == "create")
|
|
36
|
+
s"$sut($args)"
|
|
37
|
+
else if (sutFunction.toString == "add") {
|
|
38
|
+
val addArgs = sutArgs(labeledTest.result, "add")
|
|
39
|
+
s"$sut($args) ${toOperation(addArgs)} $sut(${addArgs.stripPrefix("-")})"
|
|
40
|
+
} else {
|
|
41
|
+
val argsForEqual1 = sutArgsForEqual(labeledTest.result, "clock1")
|
|
42
|
+
val argsForEqual2 = sutArgsForEqual(labeledTest.result, "clock2")
|
|
43
|
+
s"$sut($argsForEqual1) == $sut($argsForEqual2)"
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
val expected =
|
|
47
|
+
if (sutFunction.toString == "create" || sutFunction.toString == "add")
|
|
48
|
+
s"$sut(${expectedToClockStr(labeledTest.expected)})"
|
|
49
|
+
else
|
|
50
|
+
toString(labeledTest.expected)
|
|
51
|
+
|
|
52
|
+
TestCaseData(s"${labeledTest.description}", sutCall, expected)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
def main(args: Array[String]): Unit = {
|
|
56
|
+
val file = new File("src/main/resources/clock.json")
|
|
57
|
+
|
|
58
|
+
val code = TestSuiteBuilder.build(file,
|
|
59
|
+
fromLabeledTestAlt("create" -> Seq("hour", "minute"),
|
|
60
|
+
"add" -> Seq("hour", "minute"),
|
|
61
|
+
"equal" -> Seq("clock1")))
|
|
62
|
+
println(s"-------------")
|
|
63
|
+
println(code)
|
|
64
|
+
println(s"-------------")
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import java.io.File
|
|
2
|
+
|
|
3
|
+
import testgen.TestSuiteBuilder.{toString, _}
|
|
4
|
+
import testgen._
|
|
5
|
+
|
|
6
|
+
object ForthTestGenerator {
|
|
7
|
+
def main(args: Array[String]): Unit = {
|
|
8
|
+
val file = new File("src/main/resources/forth.json")
|
|
9
|
+
|
|
10
|
+
def toString(expected: CanonicalDataParser.Expected): String = {
|
|
11
|
+
expected match {
|
|
12
|
+
case Right(n: Int) => s""""${n.toString}""""
|
|
13
|
+
case Right(vals: List[Int]) => s""""${vals.map(_.toString).mkString(" ")}""""
|
|
14
|
+
case _ => throw new IllegalArgumentException
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
def isError(expected: CanonicalDataParser.Expected): Boolean = {
|
|
19
|
+
expected match {
|
|
20
|
+
case Left(_) => true
|
|
21
|
+
case Right(null) => true
|
|
22
|
+
case Right(n) => false
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
def argsToString(any: Any): String = {
|
|
27
|
+
any match {
|
|
28
|
+
case list: List[_] =>
|
|
29
|
+
val vals = list.map(s => argsToString(s)).mkString(" ")
|
|
30
|
+
s""""$vals""""
|
|
31
|
+
case str: String =>
|
|
32
|
+
s"$str"
|
|
33
|
+
case _ => any.toString
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
def sutArgs(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String =
|
|
38
|
+
argNames map (name => argsToString(parseResult(name))) mkString ", "
|
|
39
|
+
|
|
40
|
+
def fromLabeledTest(argNames: String*): ToTestCaseData =
|
|
41
|
+
withLabeledTest { sut =>
|
|
42
|
+
labeledTest =>
|
|
43
|
+
val args = sutArgs(labeledTest.result, argNames: _*)
|
|
44
|
+
val property = labeledTest.property
|
|
45
|
+
val isErr = isError(labeledTest.expected)
|
|
46
|
+
val sutCall = if (isErr)
|
|
47
|
+
s"""forth.eval($args).isLeft"""
|
|
48
|
+
else
|
|
49
|
+
s"""forth.eval($args).fold(_ => "", _.toString)"""
|
|
50
|
+
|
|
51
|
+
val expected = if (isErr)
|
|
52
|
+
"true"
|
|
53
|
+
else
|
|
54
|
+
toString(labeledTest.expected)
|
|
55
|
+
|
|
56
|
+
TestCaseData(s"${labeledTest.parentDescriptions.mkString(" - " )} - ${labeledTest.description}", sutCall, expected)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
val code =
|
|
60
|
+
TestSuiteBuilder.build(file, fromLabeledTest("input"), Seq(), Seq("private val forth = new Forth"))
|
|
61
|
+
|
|
62
|
+
println(s"-------------")
|
|
63
|
+
println(code)
|
|
64
|
+
println(s"-------------")
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import java.io.File
|
|
2
|
+
|
|
3
|
+
import testgen.TestSuiteBuilder._
|
|
4
|
+
import testgen._
|
|
5
|
+
|
|
6
|
+
object KindergartenGardenTestGenerator {
|
|
7
|
+
def main(args: Array[String]): Unit = {
|
|
8
|
+
val file = new File("src/main/resources/kindergarten-garden.json")
|
|
9
|
+
|
|
10
|
+
def toString(expected: CanonicalDataParser.Expected): String = {
|
|
11
|
+
expected match {
|
|
12
|
+
case Right(xs: List[String]) => s"List(${xs.map(x => "Plant." + x.capitalize).mkString(", ")})"
|
|
13
|
+
case _ => throw new IllegalArgumentException
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
def fromLabeledTest(argNames: String*): ToTestCaseData =
|
|
18
|
+
withLabeledTest { sut =>
|
|
19
|
+
labeledTest =>
|
|
20
|
+
val diagram = labeledTest.result("diagram")
|
|
21
|
+
val student = labeledTest.result("student")
|
|
22
|
+
val students: List[String] = (labeledTest.result getOrElse("students", List())).asInstanceOf[List[String]]
|
|
23
|
+
val property = labeledTest.property
|
|
24
|
+
val sutCall =
|
|
25
|
+
if (students.isEmpty)
|
|
26
|
+
s"""Garden.defaultGarden(${escape(diagram.toString)}).$property("$student")"""
|
|
27
|
+
else
|
|
28
|
+
s"""Garden(List(${students.map(s => escape(s)).mkString(", ")}), ${escape(diagram.toString)}).$property(${escape(student.toString)})"""
|
|
29
|
+
|
|
30
|
+
val expected = toString(labeledTest.expected)
|
|
31
|
+
TestCaseData(labeledTest.parentDescriptions.mkString(", ") + " - " + labeledTest.description,
|
|
32
|
+
sutCall, expected)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// TODO: Move this escape up to TestSuiteBuilder
|
|
36
|
+
def escape(raw: String): String = {
|
|
37
|
+
import scala.reflect.runtime.universe._
|
|
38
|
+
Literal(Constant(raw)).toString
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
val code =
|
|
42
|
+
TestSuiteBuilder.build(file, fromLabeledTest("diagram", "student"))
|
|
43
|
+
|
|
44
|
+
println(s"-------------")
|
|
45
|
+
println(code)
|
|
46
|
+
println(s"-------------")
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -7,6 +7,40 @@ object NucleotideCountTestGenerator {
|
|
|
7
7
|
def main(args: Array[String]): Unit = {
|
|
8
8
|
val file = new File("src/main/resources/nucleotide-count.json")
|
|
9
9
|
|
|
10
|
+
def mapExpectedToString(arg: Map[String, Int]): String = {
|
|
11
|
+
s"Right(Map(${arg.toSeq
|
|
12
|
+
.sortBy(_._1)
|
|
13
|
+
.map{case (key, value) => "\'" + key.toString + "\' -> " + value.toString}
|
|
14
|
+
.mkString(",\n")}))"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
def toString(expected: CanonicalDataParser.Expected): String = {
|
|
18
|
+
expected match {
|
|
19
|
+
case Left(s: String) => "true"
|
|
20
|
+
case Right(m: Map[String, Int]) => mapExpectedToString(m)
|
|
21
|
+
case _ => throw new IllegalArgumentException
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
def toSutCall(labeledTest: LabeledTest, argNames: String*): String = {
|
|
26
|
+
val args = sutArgs(labeledTest.result, argNames: _*)
|
|
27
|
+
val property = labeledTest.property
|
|
28
|
+
labeledTest.expected match {
|
|
29
|
+
case Left(_) => s"""new DNA($args).$property.isLeft"""
|
|
30
|
+
case Right(_) => s"""new DNA($args).$property"""
|
|
31
|
+
case _ => throw new IllegalArgumentException
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
def fromLabeledTest(argNames: String*): ToTestCaseData =
|
|
36
|
+
withLabeledTest { sut =>
|
|
37
|
+
labeledTest =>
|
|
38
|
+
val sutCall = toSutCall(labeledTest, argNames: _*)
|
|
39
|
+
val expected = toString(labeledTest.expected)
|
|
40
|
+
TestCaseData(labeledTest.description, sutCall, expected)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
10
44
|
val code = TestSuiteBuilder.build(file, fromLabeledTest("strand"))
|
|
11
45
|
println(s"-------------")
|
|
12
46
|
println(code)
|