trackler 2.0.8.36 → 2.0.8.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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +3 -0
  3. data/lib/trackler/version.rb +1 -1
  4. data/tracks/c/config.json +7 -0
  5. data/tracks/c/exercises/perfect-numbers/makefile +16 -0
  6. data/tracks/c/exercises/perfect-numbers/src/example.c +28 -0
  7. data/tracks/c/exercises/perfect-numbers/src/example.h +13 -0
  8. data/tracks/c/exercises/perfect-numbers/src/perfect_numbers.h +11 -0
  9. data/tracks/c/exercises/perfect-numbers/test/test_perfect_numbers.c +87 -0
  10. data/tracks/c/exercises/perfect-numbers/test/vendor/unity.c +1300 -0
  11. data/tracks/c/exercises/perfect-numbers/test/vendor/unity.h +274 -0
  12. data/tracks/c/exercises/perfect-numbers/test/vendor/unity_internals.h +701 -0
  13. data/tracks/ceylon/README.md +1 -1
  14. data/tracks/ceylon/docs/RESOURCES.md +5 -0
  15. data/tracks/ceylon/exercises/anagram/source/anagram/module.ceylon +1 -1
  16. data/tracks/ceylon/exercises/bracket-push/example/module.ceylon +2 -2
  17. data/tracks/ceylon/exercises/bracket-push/source/bracketpush/module.ceylon +1 -1
  18. data/tracks/ceylon/exercises/hamming/source/hamming/module.ceylon +1 -1
  19. data/tracks/ceylon/exercises/largest-series-product/source/largestseriesproduct/module.ceylon +1 -1
  20. data/tracks/ceylon/exercises/leap/source/leap/module.ceylon +1 -1
  21. data/tracks/ceylon/exercises/react/example/module.ceylon +2 -2
  22. data/tracks/ceylon/exercises/react/source/react/module.ceylon +1 -1
  23. data/tracks/ceylon/exercises/sieve/example/module.ceylon +2 -2
  24. data/tracks/ceylon/exercises/sieve/source/sieve/module.ceylon +1 -1
  25. data/tracks/clojurescript/.github/ISSUE_TEMPLATE.md +9 -0
  26. data/tracks/clojurescript/.gitignore +4 -0
  27. data/tracks/clojurescript/.travis.yml +5 -0
  28. data/tracks/clojurescript/LICENSE +21 -0
  29. data/tracks/clojurescript/README.md +72 -0
  30. data/tracks/clojurescript/bin/fetch-configlet +32 -0
  31. data/tracks/clojurescript/config.json +21 -0
  32. data/tracks/clojurescript/docs/ABOUT.md +0 -0
  33. data/tracks/clojurescript/docs/INSTALLATION.md +0 -0
  34. data/tracks/clojurescript/docs/LEARNING.md +0 -0
  35. data/tracks/clojurescript/docs/RESOURCES.md +0 -0
  36. data/tracks/clojurescript/docs/TESTS.md +0 -0
  37. data/tracks/clojurescript/exercises/TRACK_HINTS.md +0 -0
  38. data/tracks/clojurescript/img/.keep +0 -0
  39. data/tracks/csharp/exercises/grade-school/Example.cs +13 -1
  40. data/tracks/csharp/exercises/grade-school/GradeSchool.cs +1 -1
  41. data/tracks/csharp/exercises/grade-school/GradeSchoolTest.cs +42 -18
  42. data/tracks/go/README.md +8 -0
  43. data/tracks/go/exercises/twelve-days/HINTS.md +2 -0
  44. data/tracks/haskell/config.json +0 -1
  45. data/tracks/objective-c/config.json +9 -0
  46. data/tracks/objective-c/exercises/crypto-square/CryptoSquareExample.h +14 -0
  47. data/tracks/objective-c/exercises/crypto-square/CryptoSquareExample.m +96 -0
  48. data/tracks/objective-c/exercises/crypto-square/CryptoSquareTest.m +94 -0
  49. data/tracks/objective-c/xcodeProject/ObjectiveC.xcodeproj/project.pbxproj +18 -0
  50. data/tracks/purescript/.gitignore +2 -2
  51. data/tracks/purescript/bin/test-one.sh +58 -0
  52. data/tracks/purescript/bin/test.sh +13 -44
  53. data/tracks/purescript/config.json +7 -0
  54. data/tracks/purescript/exercises/bracket-push/bower.json +17 -0
  55. data/tracks/purescript/exercises/bracket-push/examples/src/BracketPush.purs +43 -0
  56. data/tracks/purescript/exercises/bracket-push/src/BracketPush.purs +3 -0
  57. data/tracks/purescript/exercises/bracket-push/test/Main.purs +64 -0
  58. data/tracks/scala/exercises/hello-world/HINTS.md +0 -4
  59. data/tracks/scala/exercises/hello-world/example.scala +1 -2
  60. data/tracks/scala/exercises/hello-world/src/test/scala/HelloWorldTest.scala +4 -11
  61. data/tracks/scala/testgen/build.sbt +9 -0
  62. data/tracks/scala/testgen/project/build.properties +2 -0
  63. data/tracks/scala/testgen/project/plugins.sbt +2 -0
  64. data/tracks/scala/testgen/src/main/scala/BeerSongTestGenerator.scala +15 -0
  65. data/tracks/scala/testgen/src/main/scala/BowlingTestGenerator.scala +23 -44
  66. data/tracks/scala/testgen/src/main/scala/FoodChainTestGenerator.scala +31 -0
  67. data/tracks/scala/testgen/src/main/scala/HelloWorldTestGenerator.scala +14 -0
  68. data/tracks/scala/testgen/src/main/scala/NucleotideCountTestGenerator.scala +15 -0
  69. data/tracks/scala/testgen/src/main/scala/PangramsTestGenerator.scala +20 -38
  70. data/tracks/scala/testgen/src/main/scala/SumOfMultiplesTestGenerator.scala +14 -0
  71. data/tracks/scala/testgen/src/main/scala/testgen/CanonicalDataParser.scala +105 -0
  72. data/tracks/scala/testgen/src/main/scala/testgen/TestSuiteBuilder.scala +111 -0
  73. data/tracks/scala/testgen/src/main/twirl/funSuiteTemplate.scala.txt +12 -0
  74. metadata +44 -4
  75. data/tracks/haskell/common/stack.yaml +0 -1
  76. data/tracks/haskell/exercises/pov/.dummylink +0 -1
@@ -0,0 +1,3 @@
1
+ module BracketPush
2
+ ( isPaired
3
+ ) where
@@ -0,0 +1,64 @@
1
+ module Test.Main where
2
+
3
+ import Prelude
4
+ import Control.Monad.Eff (Eff)
5
+ import Test.Unit.Assert as Assert
6
+ import Test.Unit (suite, test)
7
+ import Test.Unit.Main (runTest)
8
+ import BracketPush (isPaired)
9
+
10
+ main :: Eff _ Unit
11
+ main = runTest do
12
+ suite "BracketPush.isPaired" do
13
+
14
+ test "paired square brackets" $
15
+ Assert.equal true
16
+ (isPaired "[]")
17
+
18
+ test "empty string" $
19
+ Assert.equal true
20
+ (isPaired "")
21
+
22
+ test "unpaired brackets" $
23
+ Assert.equal false
24
+ (isPaired "[[")
25
+
26
+ test "wrong ordered brackets" $
27
+ Assert.equal false
28
+ (isPaired "}{")
29
+
30
+ test "paired with whitespace" $
31
+ Assert.equal true
32
+ (isPaired "{ }")
33
+
34
+ test "simple nested brackets" $
35
+ Assert.equal true
36
+ (isPaired "{[]}")
37
+
38
+ test "several paired brackets" $
39
+ Assert.equal true
40
+ (isPaired "{}[]")
41
+
42
+ test "paired and nested brackets" $
43
+ Assert.equal true
44
+ (isPaired "([{}({}[])])")
45
+
46
+ test "unopened closing brackets" $
47
+ Assert.equal false
48
+ (isPaired "{[)][]}")
49
+
50
+ test "unpaired and nested brackets" $
51
+ Assert.equal false
52
+ (isPaired "([{])")
53
+
54
+ test "paired and wrong nested brackets" $
55
+ Assert.equal false
56
+ (isPaired "[({]})")
57
+
58
+ test "math expression" $
59
+ Assert.equal true
60
+ (isPaired "(((185 + 223.85) * 15) - 543)/2")
61
+
62
+ test "complex latex expression" $
63
+ Assert.equal true
64
+ (isPaired "\\left(\\begin{array}{cc} \\frac{1}{3} & x\\\\ \\mathrm{e}^{x} &... x^2 \\end{array}\\right)")
@@ -1,8 +1,4 @@
1
1
  ## Hints
2
- For this exercise two Scala features come in handy:
3
- - [Default Parameter Values](http://docs.scala-lang.org/tutorials/tour/default-parameter-values.html)
4
- - [String Interpolation](http://docs.scala-lang.org/overviews/core/string-interpolation.html)
5
2
 
6
3
  #### Common pitfalls that you should avoid
7
- - `null` is usually not considered a valid value in Scala, and there are no `null` checks needed (if you don't have to interface with Java code, say). Instead there is the [Option](http://danielwestheide.com/blog/2012/12/19/the-neophytes-guide-to-scala-part-5-the-option-type.html) type if you want to express the possible absence of a value. But for this exercise just assume a normal non-`null` String parameter.
8
4
  - Usually there is no need in Scala to use `return`. For a discussion see [here](http://stackoverflow.com/questions/24856106/return-in-a-scala-function-literal). Or as a quote from that discussion: *Don't use return, it makes Scala cry.*
@@ -1,5 +1,4 @@
1
1
  object HelloWorld {
2
2
  def hello() = "Hello, World!"
3
-
4
- def hello(name: String) = s"Hello, $name!"
5
3
  }
4
+
@@ -1,17 +1,10 @@
1
1
  import org.scalatest.{Matchers, FunSuite}
2
2
 
3
+ /** @version 1.0.0 */
3
4
  class HelloWorldTest extends FunSuite with Matchers {
4
- test("Without name") {
5
- HelloWorld.hello() should be ("Hello, World!")
6
- }
7
-
8
- test("with name") {
9
- pending
10
- HelloWorld.hello("Jane") should be ("Hello, Jane!")
11
- }
12
5
 
13
- test("with umlaut name") {
14
- pending
15
- HelloWorld.hello("Jürgen") should be ("Hello, Jürgen!")
6
+ test("Say Hi!") {
7
+ HelloWorld.hello() should be ("Hello, World!")
16
8
  }
17
9
  }
10
+
@@ -2,4 +2,13 @@ name := "ExcercismScalaTestGenerator"
2
2
 
3
3
  scalaVersion := "2.11.8"
4
4
 
5
+ lazy val root = (project in file("."))
6
+ .enablePlugins(SbtTwirl)
7
+ .settings(
8
+ sourceDirectories in (Compile, TwirlKeys.compileTemplates) += (baseDirectory.value.getParentFile / "src" / "main" / "twirl"))
9
+
5
10
  libraryDependencies += "com.typesafe.play" % "play-json_2.11" % "2.5.3"
11
+
12
+ libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "1.0.4"
13
+
14
+ libraryDependencies += "com.typesafe.play" %% "twirl-api" % "1.3.0"
@@ -0,0 +1,2 @@
1
+ sbt.version=0.13.13
2
+
@@ -0,0 +1,2 @@
1
+ addSbtPlugin("com.typesafe.sbt" % "sbt-twirl" % "1.3.0")
2
+
@@ -0,0 +1,15 @@
1
+ import testgen._
2
+ import TestSuiteBuilder._
3
+ import java.io.File
4
+
5
+ object BeerSongTestGenerator {
6
+ def main(args: Array[String]): Unit = {
7
+ val file = new File("src/main/resources/beer-song.json")
8
+
9
+ val code = TestSuiteBuilder.build(file,
10
+ fromLabeledTestAlt("verse" -> Seq("number"), "verses" -> Seq("beginning", "end")))
11
+ println(s"-------------")
12
+ println(code)
13
+ println(s"-------------")
14
+ }
15
+ }
@@ -1,49 +1,28 @@
1
- import play.api.libs.json.Json
2
-
3
- import scala.io.Source
4
-
5
- class BowlingTestGenerator {
6
- implicit val testCaseReader = Json.reads[BowlingTestCase]
7
-
8
- private val filename = "bowling.json"
9
- private val fileContents = Source.fromFile(filename).getLines.mkString
10
- private val json = Json.parse(fileContents)
11
-
12
- def write {
13
- val testCases = (json \ "score" \ "cases").get.as[List[BowlingTestCase]]
14
- val description = (json \ "score" \ "description").get.as[List[String]].mkString(" ")
15
-
16
- implicit def testCaseToGen(tc: BowlingTestCase): TestCaseGen = {
17
- val callSUT =
18
- s"${tc.rolls}.foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()"
19
- val expected = ""
20
- val result = s"val score = $callSUT"
21
- val (matchRight, matchLeft) =
22
- if (tc.expected == -1)
23
- ("""fail("Unexpected score returned. Failure expected")""", "")
24
- else
25
- (s"assert(n == ${tc.expected})", s"""fail("${tc.description}")""")
26
- val checkResult =
27
- s"""score match {
28
- case Right(n) => $matchRight
29
- case Left(_) => $matchLeft
30
- }"""
31
-
32
- TestCaseGen(tc.description, callSUT, expected, result, checkResult)
33
- }
34
-
35
- val testBuilder = new TestBuilder("BowlingTest")
36
- testBuilder.addTestCases(testCases, Some(description))
37
- testBuilder.toFile
38
- }
39
- }
40
-
41
- case class BowlingTestCase(description: String,
42
- rolls: List[Int],
43
- expected: Int)
1
+ import testgen._
2
+ import TestSuiteBuilder._
3
+ import java.io.File
44
4
 
45
5
  object BowlingTestGenerator {
46
6
  def main(args: Array[String]): Unit = {
47
- new BowlingTestGenerator().write
7
+ val file = new File("src/main/resources/bowling.json")
8
+
9
+ def fromLabeledTest(argNames: String*): ToTestCaseData =
10
+ withLabeledTest { sut => labeledTest =>
11
+ val args = sutArgs(labeledTest.result, argNames: _*)
12
+ val isDefined =
13
+ labeledTest.expected.fold(Function.const(".isDefined"), Function.const(""))
14
+ val sutCall =
15
+ s"""val score = ${args}.foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
16
+ score$isDefined"""
17
+ val expected =
18
+ labeledTest.expected.fold(Function.const("true"), x => s"Some($x)")
19
+
20
+ TestCaseData(labeledTest.description, sutCall, expected)
21
+ }
22
+
23
+ val code = TestSuiteBuilder.build(file, fromLabeledTest("previous_rolls"))
24
+ println(s"-------------")
25
+ println(code)
26
+ println(s"-------------")
48
27
  }
49
28
  }
@@ -0,0 +1,31 @@
1
+ import testgen._
2
+ import TestSuiteBuilder._
3
+ import java.io.File
4
+
5
+ object FoodChainTestGenerator {
6
+ def main(args: Array[String]): Unit = {
7
+ val file = new File("src/main/resources/food-chain.json")
8
+
9
+ val RawQuote = "\"\"\""
10
+ def asRawString(str: String): String = s"$RawQuote$str$RawQuote"
11
+
12
+ def fromLabeledTest(argNames: String*)(
13
+ implicit sutFunction: LabeledTest => String = _.property): ToTestCaseData =
14
+ withLabeledTest { sut =>
15
+ labeledTest =>
16
+ val sutFunction = labeledTest.property
17
+ val args = sutArgs(labeledTest.result, argNames: _*)
18
+ val sutCall = s"$sut.$sutFunction(${args})"
19
+ val expectedLines = labeledTest.expected.right.get.asInstanceOf[List[String]]
20
+ val expected = expectedLines mkString ("", "\n", "\n\n")
21
+
22
+ TestCaseData(labeledTest.description, sutCall, asRawString(expected))
23
+ }
24
+
25
+ val code = TestSuiteBuilder.build(file,
26
+ fromLabeledTest("start verse"))
27
+ println(s"-------------")
28
+ println(code)
29
+ println(s"-------------")
30
+ }
31
+ }
@@ -0,0 +1,14 @@
1
+ import testgen._
2
+ import TestSuiteBuilder._
3
+ import java.io.File
4
+
5
+ object HelloWorldTestGenerator {
6
+ def main(args: Array[String]): Unit = {
7
+ val file = new File("src/main/resources/hello-world.json")
8
+
9
+ val code = TestSuiteBuilder.build(file, fromLabeledTest())
10
+ println(s"-------------")
11
+ println(code)
12
+ println(s"-------------")
13
+ }
14
+ }
@@ -0,0 +1,15 @@
1
+ import testgen._
2
+ import TestSuiteBuilder._
3
+ import java.io.File
4
+
5
+ object NucleotideCountTestGenerator {
6
+
7
+ def main(args: Array[String]): Unit = {
8
+ val file = new File("src/main/resources/nucleotide-count.json")
9
+
10
+ val code = TestSuiteBuilder.build(file, fromLabeledTest("strand"))
11
+ println(s"-------------")
12
+ println(code)
13
+ println(s"-------------")
14
+ }
15
+ }
@@ -1,43 +1,25 @@
1
- import play.api.libs.json.Json
2
-
3
- import scala.io.Source
4
-
5
- // Generates test suite from json definition for the Panframs exercise.
6
- class PangramsTestGenerator {
7
- implicit val pangramTestCaseReader = Json.reads[PangramTestCase]
8
-
9
- private val filename = "pangram.json"
10
- private val fileContents = Source.fromFile(filename).getLines.mkString
11
- private val json = Json.parse(fileContents)
12
-
13
- def write {
14
- print("import org.scalatest.{FunSuite, Matchers}" + System.lineSeparator())
15
- print(System.lineSeparator())
16
- print("class PangramsTest extends FunSuite with Matchers {" + System.lineSeparator())
17
-
18
- writeTestCases()
19
-
20
- print("}" + System.lineSeparator())
21
- }
22
-
23
- private def writeTestCases(): Unit = {
24
- val testCases = (json \ "cases").get.as[List[PangramTestCase]]
25
-
26
- testCases.foreach(tc => {
27
- print("\ttest(\"" + tc.description + "\") {" + System.lineSeparator())
28
-
29
- println("Pangrams.isPangram(\"" + tc.input + "\") should be (" + tc.expected + ")")
30
-
31
- print("\t}" + System.lineSeparator())
32
- print(System.lineSeparator())
33
- })
34
- }
35
- }
36
-
37
- case class PangramTestCase(description: String, input: String, expected: Boolean)
1
+ import testgen._
2
+ import TestSuiteBuilder._
3
+ import java.io.File
38
4
 
39
5
  object PangramsTestGenerator {
40
6
  def main(args: Array[String]): Unit = {
41
- new PangramsTestGenerator().write
7
+ val file = new File("src/main/resources/pangram.json")
8
+ def fromLabeledTest(argNames: String*): ToTestCaseData =
9
+ withLabeledTest { sut =>
10
+ labeledTest =>
11
+ val args = sutArgs(labeledTest.result, argNames: _*)
12
+ val isPangram = labeledTest.property.mkString
13
+ val sutCall =
14
+ s"""Pangrams.$isPangram($args)"""
15
+ val expected =
16
+ labeledTest.expected.fold(Function.const("true"), x => s"$x")
17
+ TestCaseData(labeledTest.description, sutCall, expected)
18
+ }
19
+
20
+ val code = TestSuiteBuilder.build(file, fromLabeledTest("input"))
21
+ println(s"‐‐‐‐‐‐‐‐‐‐‐‐‐")
22
+ println(code)
23
+ println(s"‐‐‐‐‐‐‐‐‐‐‐‐‐")
42
24
  }
43
25
  }
@@ -0,0 +1,14 @@
1
+ import testgen._
2
+ import TestSuiteBuilder._
3
+ import java.io.File
4
+
5
+ object SumOfMultiplesTestGenerator {
6
+ def main(args: Array[String]): Unit = {
7
+ val file = new File("src/main/resources/sum-of-multiples.json")
8
+
9
+ val code = TestSuiteBuilder.build(file, fromLabeledTest("factors", "limit"))
10
+ println(s"-------------")
11
+ println(code)
12
+ println(s"-------------")
13
+ }
14
+ }
@@ -0,0 +1,105 @@
1
+ package testgen
2
+
3
+ import scala.io.Source
4
+ import scala.util.parsing.json.JSON
5
+ import CanonicalDataParser._
6
+ import scala.util.Try
7
+ import scala.Left
8
+ import scala.Right
9
+ import java.io.File
10
+
11
+ object CanonicalDataParser {
12
+ type ParseResult = Map[String,Any]
13
+
14
+ type Description = String
15
+ type Comments = Seq[String]
16
+ type Cases = Seq[LabeledTestItem]
17
+ type Property = String
18
+ type Result = Any
19
+ type Error = String
20
+ type Expected = Either[Error, Result]
21
+ type Properties = Option[Map[String,Any]]
22
+
23
+ def getOptional[T](result: ParseResult, key: String): Option[T] =
24
+ result.get(key).asInstanceOf[Option[T]]
25
+ def getRequired[T](result: ParseResult, key: String): T =
26
+ getOptional(result, key) getOrElse (throw new Exception(s"missing: $key"))
27
+
28
+ def parse(file: File): Exercise = {
29
+ val fileContents = Source.fromFile(file).getLines.mkString
30
+ val rawParseResult =
31
+ JSON.parseFull(fileContents).get.asInstanceOf[ParseResult]
32
+ val parseResult = rawParseResult mapValues restoreInts
33
+ println(parseResult)
34
+ parseResult
35
+ }
36
+
37
+ private def restoreInts(any: Any): Any =
38
+ any match {
39
+ case double: Double if (double.toInt.toDouble == double) => double.toInt
40
+ case map: Map[_,_] => map mapValues restoreInts
41
+ case seq: Seq[_] => seq map restoreInts
42
+ case any => any
43
+ }
44
+
45
+ def main(args: Array[String]): Unit = {
46
+ val path = "src/main/resources"
47
+ // val name = "hello-world.json"
48
+ // val name = "sum-of-multiples.json"
49
+ val name = "bowling.json"
50
+ val result = parse(new File(s"$path/$name"))
51
+ println(result)
52
+ }
53
+ }
54
+
55
+ case class Exercise(name: String, version: String, cases: Cases,
56
+ comments: Option[Comments])
57
+ object Exercise {
58
+ implicit def fromParseResult(result: ParseResult): Exercise = {
59
+ val cases: Cases =
60
+ getRequired[Seq[ParseResult]](result, "cases") map LabeledTestItem.fromParseResult
61
+ Exercise(getRequired(result, "exercise"), getRequired(result, "version"),
62
+ flattenCases(cases), getOptional(result, "comments"))
63
+ }
64
+
65
+ // so far there are to few LabeledTestGroups to handle them separately
66
+ private def flattenCases(cases: Cases): Cases =
67
+ cases match {
68
+ case Seq() => Seq()
69
+ case (ltg: LabeledTestGroup) +: xs => ltg.cases ++ flattenCases(xs)
70
+ case (lt: LabeledTest) +: xs => lt +: flattenCases(xs)
71
+ }
72
+ }
73
+
74
+ sealed trait LabeledTestItem
75
+ object LabeledTestItem {
76
+ implicit def fromParseResult(result: ParseResult): LabeledTestItem =
77
+ if (result.contains("cases")) result: LabeledTestGroup
78
+ else result: LabeledTest
79
+ }
80
+
81
+ case class LabeledTest(description: Description, property: Property,
82
+ expected: Expected, result: ParseResult) extends LabeledTestItem
83
+ object LabeledTest {
84
+ implicit def fromParseResult(result: ParseResult): LabeledTest = {
85
+ val expected: Expected = {
86
+ val any = getRequired[Any](result, "expected")
87
+ val error = Try {
88
+ Left(any.asInstanceOf[Map[String,String]]("error"))
89
+ }
90
+ error.getOrElse(Right(any))
91
+ }
92
+ LabeledTest(getRequired(result, "description"), getRequired(result, "property"),
93
+ expected, result)
94
+ }
95
+ }
96
+
97
+ case class LabeledTestGroup(description: Description, cases: Cases) extends LabeledTestItem
98
+ object LabeledTestGroup {
99
+ implicit def fromParseResult(result: ParseResult): LabeledTestGroup = {
100
+ val description = getRequired[String](result, "description")
101
+ val cases =
102
+ getRequired[Seq[ParseResult]](result, "cases") map LabeledTestItem.fromParseResult
103
+ LabeledTestGroup(description, cases)
104
+ }
105
+ }