trackler 2.0.8.36 → 2.0.8.37

Sign up to get free protection for your applications and to get access to all the features.
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
+ }