trackler 2.0.3.8 → 2.0.3.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/common/exercises/book-store/description.md +67 -0
  3. data/common/exercises/book-store/metadata.yml +4 -0
  4. data/lib/trackler/version.rb +1 -1
  5. data/tracks/crystal/exercises/difference-of-squares/src/difference_of_squares.cr +1 -0
  6. data/tracks/ecmascript/exercises/custom-set/package.json +1 -0
  7. data/tracks/ecmascript/exercises/palindrome-products/palindrome-products.js +18 -18
  8. data/tracks/fsharp/docs/INSTALLATION.md +2 -3
  9. data/tracks/fsharp/docs/TESTS.md +1 -1
  10. data/tracks/fsharp/exercises/accumulate/HINTS.md +3 -0
  11. data/tracks/fsharp/exercises/diamond/HINTS.md +2 -0
  12. data/tracks/fsharp/exercises/grains/HINTS.md +1 -1
  13. data/tracks/fsharp/exercises/hello-world/HINTS.md +1 -1
  14. data/tracks/fsharp/exercises/parallel-letter-frequency/HINTS.md +3 -0
  15. data/tracks/fsharp/exercises/poker/HINTS.md +2 -0
  16. data/tracks/fsharp/exercises/raindrops/HINTS.md +2 -0
  17. data/tracks/fsharp/exercises/space-age/HINTS.md +3 -0
  18. data/tracks/javascript/exercises/bowling/bowling.spec.js +83 -63
  19. data/tracks/ocaml/config.json +5 -0
  20. data/tracks/ocaml/exercises/leap/test.ml +7 -13
  21. data/tracks/ocaml/exercises/robot-name/.merlin +3 -0
  22. data/tracks/ocaml/exercises/robot-name/Makefile +11 -0
  23. data/tracks/ocaml/exercises/robot-name/example.ml +26 -0
  24. data/tracks/ocaml/exercises/robot-name/robot_name.mli +7 -0
  25. data/tracks/ocaml/exercises/robot-name/test.ml +64 -0
  26. data/tracks/ocaml/tools/test-generator/Makefile +3 -0
  27. data/tracks/ocaml/tools/test-generator/README.md +1 -0
  28. data/tracks/ocaml/tools/test-generator/src/canonical_data_checker.ml +23 -0
  29. data/tracks/ocaml/tools/test-generator/src/controller.ml +12 -0
  30. data/tracks/ocaml/tools/test-generator/src/parser.ml +29 -22
  31. data/tracks/ocaml/tools/test-generator/src/utils.ml +8 -0
  32. data/tracks/ocaml/tools/test-generator/test/clock.json +437 -0
  33. data/tracks/ocaml/tools/test-generator/test/parser_test.ml +18 -4
  34. data/tracks/ocaml/tools/test-generator/test/with-methods-key.json +22 -0
  35. data/tracks/perl6/config.json +5 -0
  36. data/tracks/perl6/exercises/wordy/Example.p6 +16 -0
  37. data/tracks/perl6/exercises/wordy/cases.json +89 -0
  38. data/tracks/perl6/exercises/wordy/wordy.t +29 -0
  39. data/tracks/ruby/exercises/acronym/{.version → .meta/.version} +0 -0
  40. data/tracks/ruby/exercises/alphametics/{.version → .meta/.version} +0 -0
  41. data/tracks/ruby/exercises/anagram/{.version → .meta/.version} +0 -0
  42. data/tracks/ruby/exercises/binary/{.version → .meta/.version} +0 -0
  43. data/tracks/ruby/exercises/bowling/{.version → .meta/.version} +0 -0
  44. data/tracks/ruby/exercises/bracket-push/{.version → .meta/.version} +0 -0
  45. data/tracks/ruby/exercises/clock/{.version → .meta/.version} +0 -0
  46. data/tracks/ruby/exercises/connect/{.version → .meta/.version} +0 -0
  47. data/tracks/ruby/exercises/custom-set/{.version → .meta/.version} +0 -0
  48. data/tracks/ruby/exercises/difference-of-squares/{.version → .meta/.version} +0 -0
  49. data/tracks/ruby/exercises/dominoes/{.version → .meta/.version} +0 -0
  50. data/tracks/ruby/exercises/gigasecond/{.version → .meta/.version} +0 -0
  51. data/tracks/ruby/exercises/hamming/{.version → .meta/.version} +0 -0
  52. data/tracks/ruby/exercises/hello-world/{.version → .meta/.version} +0 -0
  53. data/tracks/ruby/exercises/isogram/{.version → .meta/.version} +0 -0
  54. data/tracks/ruby/exercises/largest-series-product/{.version → .meta/.version} +0 -0
  55. data/tracks/ruby/exercises/leap/{.version → .meta/.version} +0 -0
  56. data/tracks/ruby/exercises/nth-prime/{.version → .meta/.version} +0 -0
  57. data/tracks/ruby/exercises/pangram/{.version → .meta/.version} +0 -0
  58. data/tracks/ruby/exercises/queen-attack/{.version → .meta/.version} +0 -0
  59. data/tracks/ruby/exercises/raindrops/{.version → .meta/.version} +0 -0
  60. data/tracks/ruby/exercises/rna-transcription/{.version → .meta/.version} +0 -0
  61. data/tracks/ruby/exercises/roman-numerals/{.version → .meta/.version} +0 -0
  62. data/tracks/ruby/exercises/run-length-encoding/{.version → .meta/.version} +0 -0
  63. data/tracks/ruby/exercises/sieve/{.version → .meta/.version} +0 -0
  64. data/tracks/ruby/exercises/tournament/{.version → .meta/.version} +0 -0
  65. data/tracks/ruby/exercises/transpose/{.version → .meta/.version} +0 -0
  66. data/tracks/ruby/exercises/triangle/{.version → .meta/.version} +0 -0
  67. data/tracks/ruby/exercises/two-bucket/{.version → .meta/.version} +0 -0
  68. data/tracks/ruby/exercises/word-count/{.version → .meta/.version} +0 -0
  69. data/tracks/ruby/lib/generator.rb +15 -4
  70. data/tracks/rust/config.json +1 -0
  71. data/tracks/rust/exercises/largest-series-product/.gitignore +7 -0
  72. data/tracks/rust/exercises/largest-series-product/Cargo.toml +3 -0
  73. data/tracks/rust/exercises/largest-series-product/HINTS.md +6 -0
  74. data/tracks/rust/exercises/largest-series-product/example.rs +22 -0
  75. data/tracks/rust/exercises/largest-series-product/tests/largest-series-product.rs +105 -0
  76. data/tracks/rust/problems.md +1 -0
  77. data/tracks/scala/.gitignore +1 -0
  78. data/tracks/scala/exercises/accumulate/src/test/scala/{accumulate_test.scala → AccumulateTest.scala} +0 -0
  79. data/tracks/scala/exercises/allergies/src/test/scala/{allergies_test.scala → AllergiesTest.scala} +0 -0
  80. data/tracks/scala/exercises/anagram/src/test/scala/{anagram_test.scala → AnagramTest.scala} +0 -0
  81. data/tracks/scala/exercises/binary/src/test/scala/{binary_test.scala → BinaryTest.scala} +0 -0
  82. data/tracks/scala/exercises/bob/src/test/scala/{bob_test.scala → BobTest.scala} +0 -0
  83. data/tracks/scala/exercises/difference-of-squares/src/test/scala/{squares_test.scala → SquaresTest.scala} +0 -0
  84. data/tracks/scala/exercises/etl/src/test/scala/{etl_test.scala → EtlTest.scala} +0 -0
  85. data/tracks/scala/exercises/gigasecond/src/test/scala/{gigasecond_test.scala → GigasecondTest.scala} +0 -0
  86. data/tracks/scala/exercises/grade-school/src/test/scala/{grade_school_test.scala → GradeSchoolTest.scala} +0 -0
  87. data/tracks/scala/exercises/grains/src/test/scala/{grains_test.scala → GrainsTest.scala} +0 -0
  88. data/tracks/scala/exercises/hamming/src/test/scala/{hamming_test.scala → HammingTest.scala} +0 -0
  89. data/tracks/scala/exercises/hello-world/src/test/scala/HelloWorldTest.scala +2 -0
  90. data/tracks/scala/exercises/leap/src/test/scala/{leap_test.scala → LeapTest.scala} +0 -0
  91. data/tracks/scala/exercises/meetup/src/test/scala/{meetup_test.scala → MeetupTest.scala} +0 -0
  92. data/tracks/scala/exercises/nth-prime/example.scala +3 -1
  93. data/tracks/scala/exercises/nth-prime/src/test/scala/PrimeTest.scala +11 -6
  94. data/tracks/scala/exercises/nucleotide-count/src/test/scala/{nucleotide_count_test.scala → NucleotideCountTest.scala} +0 -0
  95. data/tracks/scala/exercises/palindrome-products/src/test/scala/PalindromeProductsTest.scala +7 -0
  96. data/tracks/scala/exercises/pangram/src/test/scala/{PangramsTest.scala → PangramTest.scala} +0 -0
  97. data/tracks/scala/exercises/parallel-letter-frequency/HINTS.md +26 -0
  98. data/tracks/scala/exercises/phone-number/src/test/scala/{phone_number_test.scala → PhoneNumberTest.scala} +0 -0
  99. data/tracks/scala/exercises/prime-factors/src/test/scala/{primefactors_test.scala → PrimefactorsTest.scala} +10 -0
  100. data/tracks/scala/exercises/raindrops/src/test/scala/{raindrops_test.scala → RaindropsTest.scala} +15 -0
  101. data/tracks/scala/exercises/rna-transcription/src/test/scala/{transcription_test.scala → RnaTranscriptionTest.scala} +8 -0
  102. data/tracks/scala/exercises/robot-name/src/test/scala/{robot_name_test.scala → RobotNameTest.scala} +0 -0
  103. data/tracks/scala/exercises/roman-numerals/src/test/scala/{roman_numerals_test.scala → RomanNumeralsTest.scala} +17 -0
  104. data/tracks/scala/exercises/saddle-points/src/test/scala/{SaddlePointsSpecs.scala → SaddlePointsTest.scala} +3 -0
  105. data/tracks/scala/exercises/scrabble-score/src/test/scala/{scrabble_score_test.scala → ScrabbleScoreTest.scala} +0 -0
  106. data/tracks/scala/exercises/sgf-parsing/src/test/scala/SgfTest.scala +1 -0
  107. data/tracks/scala/exercises/space-age/src/test/scala/{space_age_test.scala → SpaceAgeTest.scala} +0 -0
  108. data/tracks/scala/exercises/sublist/src/test/scala/{sublist_test.scala → SublistTest.scala} +0 -0
  109. data/tracks/scala/exercises/triangle/src/test/scala/{triangle_test.scala → TriangleTest.scala} +7 -0
  110. data/tracks/scala/exercises/word-count/src/test/scala/{word_count_test.scala → WordCountTest.scala} +0 -0
  111. data/tracks/scala/exercises/zipper/src/test/scala/ZipperTest.scala +7 -0
  112. data/tracks/swift/config.json +19 -0
  113. data/tracks/swift/docs/TESTS.md +114 -23
  114. data/tracks/swift/exercises/beer-song/BeerSongExample.swift +32 -0
  115. data/tracks/swift/exercises/beer-song/BeerSongTest.swift +44 -0
  116. data/tracks/swift/exercises/hello-world/{helloWorldExample.swift → HelloWorldExample.swift} +4 -0
  117. data/tracks/swift/exercises/hello-world/{helloWorldTest/helloWorldTest.swift → helloWorldTest.swift} +1 -1
  118. data/tracks/swift/exercises/sublist/SubListTest.swift +95 -0
  119. data/tracks/swift/exercises/sublist/SublistExample.swift +72 -0
  120. data/tracks/swift/img/page_assets/001-splash.png +0 -0
  121. data/tracks/swift/img/page_assets/002-templateChooser.png +0 -0
  122. data/tracks/swift/img/page_assets/003-nameProject.jpg +0 -0
  123. data/tracks/swift/img/page_assets/004-saveProject.jpg +0 -0
  124. data/tracks/swift/img/page_assets/005-folderLayout.png +0 -0
  125. data/tracks/swift/img/page_assets/006-newProjectInitial.jpg +0 -0
  126. data/tracks/swift/img/page_assets/007-fileInspectorUpdate.png +0 -0
  127. data/tracks/swift/img/page_assets/008-templateChooserSwift.png +0 -0
  128. data/tracks/swift/img/page_assets/009-importTestSource.png +0 -0
  129. data/tracks/swift/img/page_assets/010-testsImportExample.png +0 -0
  130. data/tracks/swift/img/page_assets/011-finalLayoutExample.png +0 -0
  131. data/tracks/swift/xcodeProject/xSwift.xcodeproj/project.pbxproj +36 -56
  132. metadata +103 -65
  133. data/tracks/swift/exercises/hello-world/helloWorld.swift +0 -1
  134. data/tracks/swift/exercises/hello-world/helloWorld.xcodeproj/project.pbxproj +0 -256
  135. data/tracks/swift/exercises/hello-world/helloWorld.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  136. data/tracks/swift/exercises/hello-world/helloWorldTest/Info.plist +0 -24
@@ -7,16 +7,19 @@ class SaddlePointsSpecs extends FlatSpec with Matchers {
7
7
  }
8
8
 
9
9
  it should "handle multiple saddles" in {
10
+ pending
10
11
  val points = Matrix(List(List(5, 3, 5, 4), List(6, 4, 7, 3), List(5, 1, 5, 3))).saddlePoints
11
12
  points should be (Set((0, 0), (0, 2), (2, 0), (2, 2)))
12
13
  }
13
14
 
14
15
  it should "handle no saddles" in {
16
+ pending
15
17
  val points = Matrix(List(List(2, 1), List(1, 2))).saddlePoints
16
18
  points should be (Set())
17
19
  }
18
20
 
19
21
  it should "handle empty matrix" in {
22
+ pending
20
23
  val points = Matrix(List()).saddlePoints
21
24
  points should be (Set())
22
25
  }
@@ -22,6 +22,7 @@ class SgfTest extends FunSuite with Matchers {
22
22
  }
23
23
 
24
24
  test("parse \"(;A[B])\"") {
25
+ pending
25
26
  Sgf.parseSgf("(;A[B])") should be (Some(Node(Map("A" -> List("B")))))
26
27
  }
27
28
 
@@ -6,30 +6,37 @@ class TriangleTest extends FlatSpec with Matchers {
6
6
  }
7
7
 
8
8
  it should "calc Equilateral2" in {
9
+ pending
9
10
  Triangle(10, 10, 10).triangleType should equal(TriangleType.Equilateral)
10
11
  }
11
12
 
12
13
  it should "calc Isosceles" in {
14
+ pending
13
15
  Triangle(3, 4, 4).triangleType should equal(TriangleType.Isosceles)
14
16
  }
15
17
 
16
18
  it should "calc Isosceles2" in {
19
+ pending
17
20
  Triangle(4, 3, 4).triangleType should equal(TriangleType.Isosceles)
18
21
  }
19
22
 
20
23
  it should "calc Scalene" in {
24
+ pending
21
25
  Triangle(3, 4, 5).triangleType should equal(TriangleType.Scalene)
22
26
  }
23
27
 
24
28
  it should "calc Illogical" in {
29
+ pending
25
30
  Triangle(1, 1, 50).triangleType should equal(TriangleType.Illogical)
26
31
  }
27
32
 
28
33
  it should "calc Illogical with zero length side" in {
34
+ pending
29
35
  Triangle(0, 2, 1).triangleType should equal(TriangleType.Illogical)
30
36
  }
31
37
 
32
38
  it should "calc Illogical with negative length side" in {
39
+ pending
33
40
  Triangle(1, 1, -1).triangleType should equal(TriangleType.Illogical)
34
41
  }
35
42
  }
@@ -23,31 +23,38 @@ class ZipperTest extends FunSuite with Matchers {
23
23
  }
24
24
 
25
25
  test("left, right and value") {
26
+ pending
26
27
  z.value(fromSome(z.right(fromSome(z.left(z.fromTree(t1)))))) should be (3)
27
28
  }
28
29
 
29
30
  test("dead end") {
31
+ pending
30
32
  (z.left(fromSome(z.left(z.fromTree(t1))))) should be (None)
31
33
  }
32
34
 
33
35
  test("tree from deep focus") {
36
+ pending
34
37
  z.toTree(fromSome(z.right(fromSome(z.left(z.fromTree(t1)))))) should be (t1)
35
38
  }
36
39
 
37
40
  test("setValue") {
41
+ pending
38
42
  z.toTree(z.setValue(5, (fromSome(z.left(z.fromTree(t1)))))) should be (t2)
39
43
  }
40
44
 
41
45
  test("setLeft with Some") {
46
+ pending
42
47
  z.toTree(z.setLeft(Some(BinTree(5, None, None)),
43
48
  (fromSome(z.left(z.fromTree(t1)))))) should be (t3)
44
49
  }
45
50
 
46
51
  test("setRight with None") {
52
+ pending
47
53
  z.toTree(z.setRight(None, (fromSome(z.left(z.fromTree(t1)))))) should be (t4)
48
54
  }
49
55
 
50
56
  test("different paths to same zipper") {
57
+ pending
51
58
  z.right(fromSome(z.up(fromSome(z.left(z.fromTree(t1)))))) should be
52
59
  (z.right(z.fromTree(t1)))
53
60
  }
@@ -222,6 +222,14 @@
222
222
  "Lists"
223
223
  ]
224
224
  },
225
+ {
226
+ "difficulty": 3,
227
+ "slug": "sublist",
228
+ "topics": [
229
+ "Looping",
230
+ "Lists"
231
+ ]
232
+ },
225
233
  {
226
234
  "difficulty": 3,
227
235
  "slug": "secret-handshake",
@@ -248,6 +256,17 @@
248
256
  "Filtering"
249
257
  ]
250
258
  },
259
+ {
260
+ "difficulty": 4,
261
+ "slug": "beer-song",
262
+ "topics": [
263
+ "Looping",
264
+ "Conditionals",
265
+ "Strings"
266
+ ]
267
+
268
+ },
269
+
251
270
  {
252
271
  "difficulty": 4,
253
272
  "slug": "twelve-days",
@@ -1,44 +1,135 @@
1
- ### Creating the project in Xcode
1
+ ## Xcode Tutorial
2
2
 
3
- Please see <a href="https://developer.apple.com/library/tvos/documentation/DeveloperTools/Conceptual/testing_with_xcode/chapters/02-quick_start.html#//apple_ref/doc/uid/TP40014132-CH2-SW1" target="_blank">Apple's guide on XCTest</a>
3
+ This guide explains how to create and configure a Swift-based Xcode project for Exercism.
4
4
 
5
- These steps will use the `bob` exercise as an example. If you are not working on `bob`, replace `bob` with your exercise name in the steps below.
5
+ Apple does not support user-defined project templates in Xcode, and the default templates are more elaborate than what is needed for Exercism. This guide bridges that gap.
6
6
 
7
- * Select iOS-->Application and then Single View Application and click Next.
7
+ These instructions are written with the expectation that some readers will be very new to Xcode. Therefore each step is described in excruciating detail. However, after a few projects, setting up a fresh project should only take a minute.
8
8
 
9
- * Enter `bob-swift`* as your Product Name, set the language to Swift, and check "Include Unit Tests", and then click Next.
9
+ _As far as housekeeping chores go, you are closer to the finish line than it appears._
10
10
 
11
- * Save the project in the same folder as the Exercism test file:
11
+ ###Overview
12
12
 
13
- ![screen shot 2016-02-29 at 1 50 17 pm](https://cloud.githubusercontent.com/assets/1554169/13405215/67123310-deeb-11e5-9a2e-7c375ee5fad6.png)
13
+ To complete an Exercism exercise, you will work primarily with three files:
14
14
 
15
- * You will see two targets in your project, one for the application named `bob-swift` and one for tests named `bob-swiftTests`. If you chose to create an OSX application instead of an iOS application, you will not see a `bob-swiftTests` target and will have to create it manually.
15
+ * **Swift Source** (HelloWorld.swift). This is the file you will create to hold your source code and it is the file you will submit to Exercism.
16
+ * **Test Source** (HelloWorldTest.swift). This file is provided by Exercism. It contains the XCTestCase subclass that defines the solution to the exercise. You never edit this file, but you will have to understand it in order to fulfill its expectations. This is also the file where you will trigger the tests and interpret the results.
17
+ * **Playground** (MyPlayground.playground) is a scratchpad for drafting code snippets and playing with ideas. The code executes as you type, providing instant feedback.
16
18
 
17
- * Drag the Exercism test file into the bob-swiftTests group, ensure that "Copy items if needed" is checked, and add the line `@testable import bob_swift ` on the second line of the Exercism test file:
19
+ When you reach the end of this tutorial, the file inspector in Xcode will look like this.
18
20
 
19
- ![screen shot 2016-02-29 at 1 50 48 pm](https://cloud.githubusercontent.com/assets/1554169/13405240/7f1aadfc-deeb-11e5-8aa5-3ca7e1a12312.png)
21
+ ![011-finalLayoutExample](/img/page_assets/011-finalLayoutExample.png)
20
22
 
21
- * Create the working file/class (in this case, `Bob.swift`), and save **in the same folder as the Exercism test file**: _[see first image]_. Then, in Xcode, drag this file inside the bob-swift folder _[see second image]_.
23
+ ### Create A New Xcode Project
22
24
 
23
- * Select `Bob.swift` and in the File Inspector make sure that both `bob-swift` and `bob-swiftTests` are checked in the Target Membership area.
25
+ ![001-splash](/img/page_assets/001-splash.png)
24
26
 
25
- * Write the solution of the exercise in your working file (Bob.swift), in order to make the tests from the test file (BobTest.swift) succeed. Now the BobTest.swift file will show you some errors, but writing the right code in your working file Bob.swift should make them disappear.
27
+ 1. Choose the second item in the list shown above to create a new project, or press Command-Shift-N.
28
+ 2. Select macOS from the row of buttons at the top of the dialog, then choose the Cocoa Application icon as shown in this image:
26
29
 
27
- * Don't write code or modify the BobTest.swift file, this file is only to verify if the code you wrote in your Bob.swift file is right. Neither add in your working file anything from the testing file, just take it as a reference to figure out how to solve the exercise. _If you prefer, you can also work in an independent Playground file and then copy your final code into your working file (Bob.swift) and continue with the testing._
30
+ ![002-templatechooser](/img/page_assets/002-templateChooser.png)
28
31
 
29
- * Then you just need to go to the Test Navigator _[see image below]_ and click on the grey play button next to the main test (BobTest in this case). If the tests passed, they will show you a green checkmark, if not, a red x mark. Modify your code on your working file (Bob.swift) until all the tests succeed.
32
+ #### Name The Project
33
+ ![003-nameproject](/img/page_assets/003-nameProject.jpg)
30
34
 
31
- <img width="256" alt="twx-runtst-6_2x" src="https://cloud.githubusercontent.com/assets/22910264/20458849/b8cd18ce-aeb0-11e6-833d-eb97aac2cb36.png">
35
+ 1. Enter `HelloWorld` as the Product Name for the project. Spaces and some punctuation symbols are acceptable, but it is better to avoid them early on. _For other exercises, replace the string `HelloWorld` with the exercise name._
36
+ 2. Fill in the Organization Name and Bundle Identifier. The Organization Name field will appear in each source file you create. The Bundle Identifier is not used in this context but should not be left blank.
37
+ 3. The Language popup should be Swift, the Include Unit Tests checkbox should be selected. All other checkboxes should be deselected.
32
38
 
33
- * Some notes: XCTestCase is the XCTest subclass that contains our tests methods and XCTAssert lines are the expected results, with different types depending on what are you testing. Learn more about XCTAssert Methods and XCTesting itself <a href="http://rshankar.com/assertions-supported-in-xctest/" target="_blank">here</a> and <a href="http://nshipster.com/xctestcase/" target="_blank">here</a>.
39
+ #### Save The Project
40
+ ![004-saveproject](/img/page_assets/004-saveProject.jpg)
34
41
 
35
- * Now run the tests, and happy coding!
42
+ 1. Choose a location to save the project. Anywhere is fine, but a good choice is inside the root folder of the current exercise.
43
+ 2. In this example, the Exercism CLI fetched an exercise into a newly created root folder named `hello-world`. The fetched contents include a readme file `README.md` and a Test Source file `HelloWorldTest.swift`.
44
+ 3. Create your project as shown in the above image, inside the root folder `hello-world`.
45
+ 4. The contents displayed inside the Xcode File Inspector do not match the arrangement of the files on the disk. This is confusing at first, but it makes sense as projects become more complex. You will need a general idea of how the layout is different in order to import files later in this tutorial. If you switch to the Finder to explore the file hierarchy now, the files on disk should look like the image below. Essentially Xcode added a new project folder named `HelloWorld` (highlighted) to the root folder `hello-world`.
36
46
 
37
- * When you are ready to submit, do so from the folder that contains the working file (`Bob.swift`) and the Exercism test file (`BobTest.swift`):
38
- `$> exercism submit Bob.swift`
47
+ ![005-folderlayout](/img/page_assets/005-folderLayout.png)
39
48
 
40
- \* Please note that I have used `bob-swift` as my example, to differentiate between the same exercise in multiple languages. If you hyphenate the project name, you will need to use an underscore instead of a hyphen in the name, in the test file. (`@testable import bob-swift` -> `@testable import bob_swift`)
49
+ #### Configure the Initial Files in the Project
41
50
 
42
- ## Running Tests
51
+ At this point the project's file inspector should look similar to the image on the left. If the `HelloWorldTests` folder is closed, click on the disclosure triangle to reveal its contents. Many of these files are not needed, so let's move them out of the way.
52
+
53
+ ![006-newprojectinitial](/img/page_assets/006-newProjectInitial.jpg)
54
+
55
+ 1. Create a new group folder 'Support' inside the main group then drag the unused files into it. As with many tasks in Xcode, there is a shortcut. In this case you could also Command-Click to select all the unneeded files, and choose `File -> New -> Group from Selection` from the contextual menu.
56
+ 2. Look at the image above on the right, note the file `HelloWorldTests.swift`. This file was provided by Xcode. Because Exercism supplies its own test file - often with a similar name - the default Xcode file is unnecessary and should be deleted. To delete the file, select it in the File Inspector and press the Delete key. In the confirmation dialog that appears, move the file to the trash.
57
+ 3. Next, create a new playground document. First, make sure to select the topmost item in the File Inspector, the item marked with a blue icon that represents the project file.
58
+ 4. Xcode provides several different options to create a new playground, including one called New Playground. However, in order for this step to work properly follow this exactly: press Command-N and choose Playground from the template chooser. Click Next, and click Create.
59
+
60
+ At this stage, the File Inspector should appear like this:
61
+
62
+ ![007-fileInspectorUpdate](/img/page_assets/007-fileInspectorUpdate.png)
63
+
64
+ #### Make A New Swift Source File For Your Code
65
+
66
+ ![008-templateChooserSwift](/img/page_assets/008-templateChooserSwift.png)
67
+
68
+ 1. Press Command-N to open the template chooser. Select macOS the Swift File icon, as shown above.
69
+ 2. Near the bottom of the Save As dialog that appears next, set the Group to `HelloWorld` and select only `HelloWorld` from the Targets list.
70
+ 3. The filename is up to you and can be changed later. The project name, `HelloWorld`, is a good first choice. By convention Swift classes and structs begin with a capital letter, so their source files should as well.
71
+ 4. Click Create. **Note this is the file you will submit to the Exercism web site for review.**
72
+
73
+ *Xcode note: If the file appeared in the wrong place, drag it into its preferred position.*
74
+
75
+ #### Import The Exercism Test Source File
76
+
77
+ In the Finder, locate the root folder `hello-world` for this exercise. Drag the file `HelloWorldTest.swift` into the File Inspector so that it inserts into the `HelloWorldTests` group. When the import dialog appears, it should be set up like this:
78
+
79
+ ![009-importTestSource](/img/page_assets/009-importTestSource.png)
80
+
81
+ Select the newly imported file in the File Inspector to open the source code. Add the line `@testable import HelloWorld` above the class declaration. (When the Xcode project name contains a hyphen, replace it with an underscore. For example, `Word-Count` would become `Word-Count`.) The image below shows how the document should appear. Red errors are likely at this stage, and normal.
82
+
83
+ ![010-testsImportExample](/img/page_assets/010-testsImportExample.png)
84
+
85
+ Here is how the file inspector should look now:
86
+
87
+ ![011-finallayoutexample](/img/page_assets/011-finalLayoutExample.png)
88
+
89
+ The housekeeping is finished and Xcode is ready! To review:
90
+
91
+ * **HelloWorld.swift** is the Swift Source code file where you code the solution and later submit it to Exercism.
92
+ * **HelloWorldTest.swift** is the Test Source code file provided by Exercism. It contains the tests that define the exercise.
93
+ * **MyPlayground.playground** is for drafting code snippets and playing with ideas.
94
+
95
+ ### How Tests Are Used
96
+
97
+ Test driven development is a very iterative process. The first step is to successfully run the tests (see the next section), and have them fail. Remember that the exercise can be solved with code in the application source file alone. Enter your solution into the Swift Source file. As you type, Xcode will continuously update the display with errors that highlight code that will not compile.
98
+
99
+ One approach begins with creating a method that returns a correct hard coded value to at least the first test in order for the project to compile. This should confirm that Xcode is passing values between the code and tests properly. Next, create code that generates the expected return value and test again. Keep repeating this basic cycle until all the tests pass.
100
+
101
+ #### Running The Tests
102
+
103
+ Trigger a test by clicking on one of the diamonds in the gutter of the Tests Source file. The diamond next to the class definition will run all the tests, whereas the diamond next to each individual test will run only that test.
104
+
105
+ Tests can also be invoked with Command-U, or from the Test Inspector (Command-5).
106
+
107
+ Once all the tests are marked with a green icon, congratulations, you have successfully completed the exercise! Now submit it to the Exercism website for review. If you are impossibly stuck, submit the exercise before it is complete to view how other users solved the exercise.
108
+
109
+ *The Hello-World exercise is a very simple coding problem, but the complexity of Xcode can make even simple exercises challenging. If creating a working solution is problematic, the issue may be with how the project is configured. Consider submitting the unfinished exercise to obtain a solution. Then try repeating this tutorial from the beginning with a fresh Xcode project.*
110
+
111
+ ### Submission
112
+
113
+ 1. In the Terminal, navigate to the folder that contains the application source file. In this example, the path would be `~/exercism/swift/hello-world/HelloWorld/HelloWorld/`
114
+ 2. To submit, type `exercism submit HelloWorld.swift` (_Alternatively, you can submit by using the file name with the full path from any directory. A second alternative is to locate the file you need to submit in the Finder. Open the Terminal, type exercism submit followed by a space, then drag the file from the Finder into the Terminal and press return._)
115
+ 3. Once uploaded, a URL will appear that reveals your solution on the Exercism web site.
116
+ 4. The Exercism CLI allows files to be submitted more than once, and each successive iteration will be added alongside the original.
117
+
118
+ ### Participate in Code Reviews
119
+
120
+ After you submit a file, follow the URL presented to show the submission on the web. Bookmark it for future reference. From your submission page you can view how others solved the same problem.
121
+
122
+ ### More Information
123
+
124
+ XCTestCase is the XCTest subclass that contains the test's methods and XCTAssert lines are the expected results. The results are different types depending on how the test is designed.
125
+
126
+ There is a lot more to learn more about Test Driven Development, XCTAssert Methods and XCTestCase. Unfortunately up-to-date Swift documentation on these topics is short-lived. Although out of date as of when this tutorial was last updated, this curated list of sources contains useful information:
127
+
128
+ [Apple's Guide on XCTest](https://developer.apple.com/library/tvos/documentation/DeveloperTools/Conceptual/testing_with_xcode/chapters/02-quick_start.html#//apple_ref/doc/uid/TP40014132-CH2-SW1)
129
+
130
+ [XCTest​Case / XCTest​Expectation / measure​Block()](http://nshipster.com/xctestcase/)
131
+
132
+ A list of [Assertions supported in XCTest](http://rshankar.com/assertions-supported-in-xctest/).
133
+
134
+ [Getting Started with TDD in Swift 2.0](https://medium.com/@ynzc/getting-started-with-tdd-in-swift-2fab3e07204b#.589p6ao6y)
43
135
 
44
- Test will run through the Xcode GUI using the XCTest framework.
@@ -0,0 +1,32 @@
1
+ struct BeerSong {
2
+
3
+ var numberOfBeerBottles: Int
4
+ func generateVersesOfBeerSong() -> String {
5
+ var verses = ""
6
+ var numberOfBottlesOfBeer = numberOfBeerBottles
7
+ while numberOfBottlesOfBeer > 2 {
8
+ verses.append("\(numberOfBottlesOfBeer) bottles of beer on the wall, \(numberOfBottlesOfBeer) bottles of beer.\n")
9
+ numberOfBottlesOfBeer -= 1
10
+ verses.append("Take one down and pass it around, \(numberOfBottlesOfBeer) bottles of beer on the wall.\n\n")
11
+ }
12
+ while numberOfBottlesOfBeer <= 2 {
13
+ switch numberOfBottlesOfBeer {
14
+ case 2:verses.append("\(numberOfBottlesOfBeer) bottles of beer on the wall, \(numberOfBottlesOfBeer) bottles of beer.\n")
15
+ numberOfBottlesOfBeer -= 1
16
+ verses.append("Take one down and pass it around, \(numberOfBottlesOfBeer) bottle of beer on the wall.\n\n")
17
+
18
+ case 1:verses.append("\(numberOfBottlesOfBeer) bottle of beer on the wall, \(numberOfBottlesOfBeer) bottle of beer.\n")
19
+ numberOfBottlesOfBeer -= 1
20
+ verses.append("Take one down and pass it around, no more bottles of beer on the wall.\n\n")
21
+
22
+ case 0:verses.append("No more bottles of beer on the wall, no more bottles of beer.\n")
23
+ numberOfBottlesOfBeer = 99
24
+ verses.append("Go to the store and buy some more, \(numberOfBottlesOfBeer) bottles of beer on the wall.")
25
+ default:break
26
+ }
27
+
28
+ }
29
+ return verses
30
+ }
31
+
32
+ }
@@ -0,0 +1,44 @@
1
+ #if swift(>=3.0)
2
+ import XCTest
3
+ #endif
4
+
5
+ class BeerSongTest: XCTestCase {
6
+
7
+ func testGenerateVerseForZeroBeerBottles() {
8
+
9
+ let beerSongForZeroBeerBottles = BeerSong(numberOfBeerBottles: 0)
10
+ let expectedVerses = "No more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall."
11
+ XCTAssertEqual(expectedVerses, beerSongForZeroBeerBottles.generateVersesOfBeerSong())
12
+
13
+ }
14
+
15
+ func testGenerateVerseForOneBeerBottle() {
16
+
17
+ let beerSongForOneBeerBottle = BeerSong(numberOfBeerBottles: 1)
18
+ let expectedVerses = "1 bottle of beer on the wall, 1 bottle of beer.\nTake one down and pass it around, no more bottles of beer on the wall.\n\nNo more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall."
19
+ XCTAssertEqual(expectedVerses, beerSongForOneBeerBottle.generateVersesOfBeerSong())
20
+ }
21
+
22
+ func testGenerateVersesForTwoBeerBottles() {
23
+
24
+ let beerSongForTwoBeerBottles = BeerSong(numberOfBeerBottles: 2)
25
+ let expectedVerses = "2 bottles of beer on the wall, 2 bottles of beer.\nTake one down and pass it around, 1 bottle of beer on the wall.\n\n1 bottle of beer on the wall, 1 bottle of beer.\nTake one down and pass it around, no more bottles of beer on the wall.\n\nNo more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall."
26
+ XCTAssertEqual(expectedVerses, beerSongForTwoBeerBottles.generateVersesOfBeerSong())
27
+
28
+ }
29
+
30
+ func testGenerateVersesForFiftyEightBeerBottles() {
31
+
32
+ let beerSongForFiftyEightBeerBottles = BeerSong(numberOfBeerBottles: 58)
33
+ let expectedVerses = "58 bottles of beer on the wall, 58 bottles of beer.\nTake one down and pass it around, 57 bottles of beer on the wall.\n\n57 bottles of beer on the wall, 57 bottles of beer.\nTake one down and pass it around, 56 bottles of beer on the wall.\n\n56 bottles of beer on the wall, 56 bottles of beer.\nTake one down and pass it around, 55 bottles of beer on the wall.\n\n55 bottles of beer on the wall, 55 bottles of beer.\nTake one down and pass it around, 54 bottles of beer on the wall.\n\n54 bottles of beer on the wall, 54 bottles of beer.\nTake one down and pass it around, 53 bottles of beer on the wall.\n\n53 bottles of beer on the wall, 53 bottles of beer.\nTake one down and pass it around, 52 bottles of beer on the wall.\n\n52 bottles of beer on the wall, 52 bottles of beer.\nTake one down and pass it around, 51 bottles of beer on the wall.\n\n51 bottles of beer on the wall, 51 bottles of beer.\nTake one down and pass it around, 50 bottles of beer on the wall.\n\n50 bottles of beer on the wall, 50 bottles of beer.\nTake one down and pass it around, 49 bottles of beer on the wall.\n\n49 bottles of beer on the wall, 49 bottles of beer.\nTake one down and pass it around, 48 bottles of beer on the wall.\n\n48 bottles of beer on the wall, 48 bottles of beer.\nTake one down and pass it around, 47 bottles of beer on the wall.\n\n47 bottles of beer on the wall, 47 bottles of beer.\nTake one down and pass it around, 46 bottles of beer on the wall.\n\n46 bottles of beer on the wall, 46 bottles of beer.\nTake one down and pass it around, 45 bottles of beer on the wall.\n\n45 bottles of beer on the wall, 45 bottles of beer.\nTake one down and pass it around, 44 bottles of beer on the wall.\n\n44 bottles of beer on the wall, 44 bottles of beer.\nTake one down and pass it around, 43 bottles of beer on the wall.\n\n43 bottles of beer on the wall, 43 bottles of beer.\nTake one down and pass it around, 42 bottles of beer on the wall.\n\n42 bottles of beer on the wall, 42 bottles of beer.\nTake one down and pass it around, 41 bottles of beer on the wall.\n\n41 bottles of beer on the wall, 41 bottles of beer.\nTake one down and pass it around, 40 bottles of beer on the wall.\n\n40 bottles of beer on the wall, 40 bottles of beer.\nTake one down and pass it around, 39 bottles of beer on the wall.\n\n39 bottles of beer on the wall, 39 bottles of beer.\nTake one down and pass it around, 38 bottles of beer on the wall.\n\n38 bottles of beer on the wall, 38 bottles of beer.\nTake one down and pass it around, 37 bottles of beer on the wall.\n\n37 bottles of beer on the wall, 37 bottles of beer.\nTake one down and pass it around, 36 bottles of beer on the wall.\n\n36 bottles of beer on the wall, 36 bottles of beer.\nTake one down and pass it around, 35 bottles of beer on the wall.\n\n35 bottles of beer on the wall, 35 bottles of beer.\nTake one down and pass it around, 34 bottles of beer on the wall.\n\n34 bottles of beer on the wall, 34 bottles of beer.\nTake one down and pass it around, 33 bottles of beer on the wall.\n\n33 bottles of beer on the wall, 33 bottles of beer.\nTake one down and pass it around, 32 bottles of beer on the wall.\n\n32 bottles of beer on the wall, 32 bottles of beer.\nTake one down and pass it around, 31 bottles of beer on the wall.\n\n31 bottles of beer on the wall, 31 bottles of beer.\nTake one down and pass it around, 30 bottles of beer on the wall.\n\n30 bottles of beer on the wall, 30 bottles of beer.\nTake one down and pass it around, 29 bottles of beer on the wall.\n\n29 bottles of beer on the wall, 29 bottles of beer.\nTake one down and pass it around, 28 bottles of beer on the wall.\n\n28 bottles of beer on the wall, 28 bottles of beer.\nTake one down and pass it around, 27 bottles of beer on the wall.\n\n27 bottles of beer on the wall, 27 bottles of beer.\nTake one down and pass it around, 26 bottles of beer on the wall.\n\n26 bottles of beer on the wall, 26 bottles of beer.\nTake one down and pass it around, 25 bottles of beer on the wall.\n\n25 bottles of beer on the wall, 25 bottles of beer.\nTake one down and pass it around, 24 bottles of beer on the wall.\n\n24 bottles of beer on the wall, 24 bottles of beer.\nTake one down and pass it around, 23 bottles of beer on the wall.\n\n23 bottles of beer on the wall, 23 bottles of beer.\nTake one down and pass it around, 22 bottles of beer on the wall.\n\n22 bottles of beer on the wall, 22 bottles of beer.\nTake one down and pass it around, 21 bottles of beer on the wall.\n\n21 bottles of beer on the wall, 21 bottles of beer.\nTake one down and pass it around, 20 bottles of beer on the wall.\n\n20 bottles of beer on the wall, 20 bottles of beer.\nTake one down and pass it around, 19 bottles of beer on the wall.\n\n19 bottles of beer on the wall, 19 bottles of beer.\nTake one down and pass it around, 18 bottles of beer on the wall.\n\n18 bottles of beer on the wall, 18 bottles of beer.\nTake one down and pass it around, 17 bottles of beer on the wall.\n\n17 bottles of beer on the wall, 17 bottles of beer.\nTake one down and pass it around, 16 bottles of beer on the wall.\n\n16 bottles of beer on the wall, 16 bottles of beer.\nTake one down and pass it around, 15 bottles of beer on the wall.\n\n15 bottles of beer on the wall, 15 bottles of beer.\nTake one down and pass it around, 14 bottles of beer on the wall.\n\n14 bottles of beer on the wall, 14 bottles of beer.\nTake one down and pass it around, 13 bottles of beer on the wall.\n\n13 bottles of beer on the wall, 13 bottles of beer.\nTake one down and pass it around, 12 bottles of beer on the wall.\n\n12 bottles of beer on the wall, 12 bottles of beer.\nTake one down and pass it around, 11 bottles of beer on the wall.\n\n11 bottles of beer on the wall, 11 bottles of beer.\nTake one down and pass it around, 10 bottles of beer on the wall.\n\n10 bottles of beer on the wall, 10 bottles of beer.\nTake one down and pass it around, 9 bottles of beer on the wall.\n\n9 bottles of beer on the wall, 9 bottles of beer.\nTake one down and pass it around, 8 bottles of beer on the wall.\n\n8 bottles of beer on the wall, 8 bottles of beer.\nTake one down and pass it around, 7 bottles of beer on the wall.\n\n7 bottles of beer on the wall, 7 bottles of beer.\nTake one down and pass it around, 6 bottles of beer on the wall.\n\n6 bottles of beer on the wall, 6 bottles of beer.\nTake one down and pass it around, 5 bottles of beer on the wall.\n\n5 bottles of beer on the wall, 5 bottles of beer.\nTake one down and pass it around, 4 bottles of beer on the wall.\n\n4 bottles of beer on the wall, 4 bottles of beer.\nTake one down and pass it around, 3 bottles of beer on the wall.\n\n3 bottles of beer on the wall, 3 bottles of beer.\nTake one down and pass it around, 2 bottles of beer on the wall.\n\n2 bottles of beer on the wall, 2 bottles of beer.\nTake one down and pass it around, 1 bottle of beer on the wall.\n\n1 bottle of beer on the wall, 1 bottle of beer.\nTake one down and pass it around, no more bottles of beer on the wall.\n\nNo more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall."
34
+ XCTAssertEqual(expectedVerses, beerSongForFiftyEightBeerBottles.generateVersesOfBeerSong())
35
+ }
36
+
37
+ func testGenerateAllSongVerses() {
38
+
39
+ let beerSong = BeerSong(numberOfBeerBottles: 99)
40
+ let expectedVerses = "99 bottles of beer on the wall, 99 bottles of beer.\nTake one down and pass it around, 98 bottles of beer on the wall.\n\n98 bottles of beer on the wall, 98 bottles of beer.\nTake one down and pass it around, 97 bottles of beer on the wall.\n\n97 bottles of beer on the wall, 97 bottles of beer.\nTake one down and pass it around, 96 bottles of beer on the wall.\n\n96 bottles of beer on the wall, 96 bottles of beer.\nTake one down and pass it around, 95 bottles of beer on the wall.\n\n95 bottles of beer on the wall, 95 bottles of beer.\nTake one down and pass it around, 94 bottles of beer on the wall.\n\n94 bottles of beer on the wall, 94 bottles of beer.\nTake one down and pass it around, 93 bottles of beer on the wall.\n\n93 bottles of beer on the wall, 93 bottles of beer.\nTake one down and pass it around, 92 bottles of beer on the wall.\n\n92 bottles of beer on the wall, 92 bottles of beer.\nTake one down and pass it around, 91 bottles of beer on the wall.\n\n91 bottles of beer on the wall, 91 bottles of beer.\nTake one down and pass it around, 90 bottles of beer on the wall.\n\n90 bottles of beer on the wall, 90 bottles of beer.\nTake one down and pass it around, 89 bottles of beer on the wall.\n\n89 bottles of beer on the wall, 89 bottles of beer.\nTake one down and pass it around, 88 bottles of beer on the wall.\n\n88 bottles of beer on the wall, 88 bottles of beer.\nTake one down and pass it around, 87 bottles of beer on the wall.\n\n87 bottles of beer on the wall, 87 bottles of beer.\nTake one down and pass it around, 86 bottles of beer on the wall.\n\n86 bottles of beer on the wall, 86 bottles of beer.\nTake one down and pass it around, 85 bottles of beer on the wall.\n\n85 bottles of beer on the wall, 85 bottles of beer.\nTake one down and pass it around, 84 bottles of beer on the wall.\n\n84 bottles of beer on the wall, 84 bottles of beer.\nTake one down and pass it around, 83 bottles of beer on the wall.\n\n83 bottles of beer on the wall, 83 bottles of beer.\nTake one down and pass it around, 82 bottles of beer on the wall.\n\n82 bottles of beer on the wall, 82 bottles of beer.\nTake one down and pass it around, 81 bottles of beer on the wall.\n\n81 bottles of beer on the wall, 81 bottles of beer.\nTake one down and pass it around, 80 bottles of beer on the wall.\n\n80 bottles of beer on the wall, 80 bottles of beer.\nTake one down and pass it around, 79 bottles of beer on the wall.\n\n79 bottles of beer on the wall, 79 bottles of beer.\nTake one down and pass it around, 78 bottles of beer on the wall.\n\n78 bottles of beer on the wall, 78 bottles of beer.\nTake one down and pass it around, 77 bottles of beer on the wall.\n\n77 bottles of beer on the wall, 77 bottles of beer.\nTake one down and pass it around, 76 bottles of beer on the wall.\n\n76 bottles of beer on the wall, 76 bottles of beer.\nTake one down and pass it around, 75 bottles of beer on the wall.\n\n75 bottles of beer on the wall, 75 bottles of beer.\nTake one down and pass it around, 74 bottles of beer on the wall.\n\n74 bottles of beer on the wall, 74 bottles of beer.\nTake one down and pass it around, 73 bottles of beer on the wall.\n\n73 bottles of beer on the wall, 73 bottles of beer.\nTake one down and pass it around, 72 bottles of beer on the wall.\n\n72 bottles of beer on the wall, 72 bottles of beer.\nTake one down and pass it around, 71 bottles of beer on the wall.\n\n71 bottles of beer on the wall, 71 bottles of beer.\nTake one down and pass it around, 70 bottles of beer on the wall.\n\n70 bottles of beer on the wall, 70 bottles of beer.\nTake one down and pass it around, 69 bottles of beer on the wall.\n\n69 bottles of beer on the wall, 69 bottles of beer.\nTake one down and pass it around, 68 bottles of beer on the wall.\n\n68 bottles of beer on the wall, 68 bottles of beer.\nTake one down and pass it around, 67 bottles of beer on the wall.\n\n67 bottles of beer on the wall, 67 bottles of beer.\nTake one down and pass it around, 66 bottles of beer on the wall.\n\n66 bottles of beer on the wall, 66 bottles of beer.\nTake one down and pass it around, 65 bottles of beer on the wall.\n\n65 bottles of beer on the wall, 65 bottles of beer.\nTake one down and pass it around, 64 bottles of beer on the wall.\n\n64 bottles of beer on the wall, 64 bottles of beer.\nTake one down and pass it around, 63 bottles of beer on the wall.\n\n63 bottles of beer on the wall, 63 bottles of beer.\nTake one down and pass it around, 62 bottles of beer on the wall.\n\n62 bottles of beer on the wall, 62 bottles of beer.\nTake one down and pass it around, 61 bottles of beer on the wall.\n\n61 bottles of beer on the wall, 61 bottles of beer.\nTake one down and pass it around, 60 bottles of beer on the wall.\n\n60 bottles of beer on the wall, 60 bottles of beer.\nTake one down and pass it around, 59 bottles of beer on the wall.\n\n59 bottles of beer on the wall, 59 bottles of beer.\nTake one down and pass it around, 58 bottles of beer on the wall.\n\n58 bottles of beer on the wall, 58 bottles of beer.\nTake one down and pass it around, 57 bottles of beer on the wall.\n\n57 bottles of beer on the wall, 57 bottles of beer.\nTake one down and pass it around, 56 bottles of beer on the wall.\n\n56 bottles of beer on the wall, 56 bottles of beer.\nTake one down and pass it around, 55 bottles of beer on the wall.\n\n55 bottles of beer on the wall, 55 bottles of beer.\nTake one down and pass it around, 54 bottles of beer on the wall.\n\n54 bottles of beer on the wall, 54 bottles of beer.\nTake one down and pass it around, 53 bottles of beer on the wall.\n\n53 bottles of beer on the wall, 53 bottles of beer.\nTake one down and pass it around, 52 bottles of beer on the wall.\n\n52 bottles of beer on the wall, 52 bottles of beer.\nTake one down and pass it around, 51 bottles of beer on the wall.\n\n51 bottles of beer on the wall, 51 bottles of beer.\nTake one down and pass it around, 50 bottles of beer on the wall.\n\n50 bottles of beer on the wall, 50 bottles of beer.\nTake one down and pass it around, 49 bottles of beer on the wall.\n\n49 bottles of beer on the wall, 49 bottles of beer.\nTake one down and pass it around, 48 bottles of beer on the wall.\n\n48 bottles of beer on the wall, 48 bottles of beer.\nTake one down and pass it around, 47 bottles of beer on the wall.\n\n47 bottles of beer on the wall, 47 bottles of beer.\nTake one down and pass it around, 46 bottles of beer on the wall.\n\n46 bottles of beer on the wall, 46 bottles of beer.\nTake one down and pass it around, 45 bottles of beer on the wall.\n\n45 bottles of beer on the wall, 45 bottles of beer.\nTake one down and pass it around, 44 bottles of beer on the wall.\n\n44 bottles of beer on the wall, 44 bottles of beer.\nTake one down and pass it around, 43 bottles of beer on the wall.\n\n43 bottles of beer on the wall, 43 bottles of beer.\nTake one down and pass it around, 42 bottles of beer on the wall.\n\n42 bottles of beer on the wall, 42 bottles of beer.\nTake one down and pass it around, 41 bottles of beer on the wall.\n\n41 bottles of beer on the wall, 41 bottles of beer.\nTake one down and pass it around, 40 bottles of beer on the wall.\n\n40 bottles of beer on the wall, 40 bottles of beer.\nTake one down and pass it around, 39 bottles of beer on the wall.\n\n39 bottles of beer on the wall, 39 bottles of beer.\nTake one down and pass it around, 38 bottles of beer on the wall.\n\n38 bottles of beer on the wall, 38 bottles of beer.\nTake one down and pass it around, 37 bottles of beer on the wall.\n\n37 bottles of beer on the wall, 37 bottles of beer.\nTake one down and pass it around, 36 bottles of beer on the wall.\n\n36 bottles of beer on the wall, 36 bottles of beer.\nTake one down and pass it around, 35 bottles of beer on the wall.\n\n35 bottles of beer on the wall, 35 bottles of beer.\nTake one down and pass it around, 34 bottles of beer on the wall.\n\n34 bottles of beer on the wall, 34 bottles of beer.\nTake one down and pass it around, 33 bottles of beer on the wall.\n\n33 bottles of beer on the wall, 33 bottles of beer.\nTake one down and pass it around, 32 bottles of beer on the wall.\n\n32 bottles of beer on the wall, 32 bottles of beer.\nTake one down and pass it around, 31 bottles of beer on the wall.\n\n31 bottles of beer on the wall, 31 bottles of beer.\nTake one down and pass it around, 30 bottles of beer on the wall.\n\n30 bottles of beer on the wall, 30 bottles of beer.\nTake one down and pass it around, 29 bottles of beer on the wall.\n\n29 bottles of beer on the wall, 29 bottles of beer.\nTake one down and pass it around, 28 bottles of beer on the wall.\n\n28 bottles of beer on the wall, 28 bottles of beer.\nTake one down and pass it around, 27 bottles of beer on the wall.\n\n27 bottles of beer on the wall, 27 bottles of beer.\nTake one down and pass it around, 26 bottles of beer on the wall.\n\n26 bottles of beer on the wall, 26 bottles of beer.\nTake one down and pass it around, 25 bottles of beer on the wall.\n\n25 bottles of beer on the wall, 25 bottles of beer.\nTake one down and pass it around, 24 bottles of beer on the wall.\n\n24 bottles of beer on the wall, 24 bottles of beer.\nTake one down and pass it around, 23 bottles of beer on the wall.\n\n23 bottles of beer on the wall, 23 bottles of beer.\nTake one down and pass it around, 22 bottles of beer on the wall.\n\n22 bottles of beer on the wall, 22 bottles of beer.\nTake one down and pass it around, 21 bottles of beer on the wall.\n\n21 bottles of beer on the wall, 21 bottles of beer.\nTake one down and pass it around, 20 bottles of beer on the wall.\n\n20 bottles of beer on the wall, 20 bottles of beer.\nTake one down and pass it around, 19 bottles of beer on the wall.\n\n19 bottles of beer on the wall, 19 bottles of beer.\nTake one down and pass it around, 18 bottles of beer on the wall.\n\n18 bottles of beer on the wall, 18 bottles of beer.\nTake one down and pass it around, 17 bottles of beer on the wall.\n\n17 bottles of beer on the wall, 17 bottles of beer.\nTake one down and pass it around, 16 bottles of beer on the wall.\n\n16 bottles of beer on the wall, 16 bottles of beer.\nTake one down and pass it around, 15 bottles of beer on the wall.\n\n15 bottles of beer on the wall, 15 bottles of beer.\nTake one down and pass it around, 14 bottles of beer on the wall.\n\n14 bottles of beer on the wall, 14 bottles of beer.\nTake one down and pass it around, 13 bottles of beer on the wall.\n\n13 bottles of beer on the wall, 13 bottles of beer.\nTake one down and pass it around, 12 bottles of beer on the wall.\n\n12 bottles of beer on the wall, 12 bottles of beer.\nTake one down and pass it around, 11 bottles of beer on the wall.\n\n11 bottles of beer on the wall, 11 bottles of beer.\nTake one down and pass it around, 10 bottles of beer on the wall.\n\n10 bottles of beer on the wall, 10 bottles of beer.\nTake one down and pass it around, 9 bottles of beer on the wall.\n\n9 bottles of beer on the wall, 9 bottles of beer.\nTake one down and pass it around, 8 bottles of beer on the wall.\n\n8 bottles of beer on the wall, 8 bottles of beer.\nTake one down and pass it around, 7 bottles of beer on the wall.\n\n7 bottles of beer on the wall, 7 bottles of beer.\nTake one down and pass it around, 6 bottles of beer on the wall.\n\n6 bottles of beer on the wall, 6 bottles of beer.\nTake one down and pass it around, 5 bottles of beer on the wall.\n\n5 bottles of beer on the wall, 5 bottles of beer.\nTake one down and pass it around, 4 bottles of beer on the wall.\n\n4 bottles of beer on the wall, 4 bottles of beer.\nTake one down and pass it around, 3 bottles of beer on the wall.\n\n3 bottles of beer on the wall, 3 bottles of beer.\nTake one down and pass it around, 2 bottles of beer on the wall.\n\n2 bottles of beer on the wall, 2 bottles of beer.\nTake one down and pass it around, 1 bottle of beer on the wall.\n\n1 bottle of beer on the wall, 1 bottle of beer.\nTake one down and pass it around, no more bottles of beer on the wall.\n\nNo more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall."
41
+ XCTAssertEqual(expectedVerses, beerSong.generateVersesOfBeerSong())
42
+ }
43
+
44
+ }
@@ -1,3 +1,7 @@
1
+ //
2
+ // HelloWorld.swift
3
+ //
4
+
1
5
  struct HelloWorld {
2
6
  static func hello(_ text: String = "World") -> String {
3
7
  return "Hello, \(text)!"
@@ -2,7 +2,7 @@
2
2
  import XCTest
3
3
  #endif
4
4
 
5
- class HelloWorldTest: XCTestCase {
5
+ class HelloWorldTest: XCTestCase {
6
6
 
7
7
  func testNoName() {
8
8
  let expected = "Hello, World!"
@@ -0,0 +1,95 @@
1
+ import XCTest
2
+
3
+ class SubListTest: XCTestCase {
4
+
5
+ func testEmptyLists() {
6
+
7
+ XCTAssertEqual(.equal, classifier(listOne: [], listTwo: []) )
8
+ }
9
+
10
+ func testEmptyListWithinNonEmptyList() {
11
+
12
+ XCTAssertEqual(.sublist, classifier(listOne: [], listTwo: [1, 2, 3]))
13
+ }
14
+
15
+ func testNonEmptyListContainingEmptyList() {
16
+
17
+ XCTAssertEqual(.superlist, classifier(listOne: [1, 2, 3], listTwo: []))
18
+ }
19
+
20
+ func testEqualLists() {
21
+
22
+ XCTAssertEqual(.equal, classifier(listOne: [1, 2, 3], listTwo: [1, 2, 3]))
23
+ }
24
+
25
+ func testDifferentLists() {
26
+
27
+ XCTAssertEqual(.unequal, classifier(listOne: [1, 2, 3], listTwo: [2, 3, 4]))
28
+ }
29
+
30
+ func testFalseStart() {
31
+
32
+ XCTAssertEqual(.sublist, classifier(listOne: [1, 2, 5], listTwo: [0, 1, 2, 3, 1, 2, 5, 6]))
33
+ }
34
+
35
+ func testConsecutive() {
36
+
37
+ XCTAssertEqual(.sublist, classifier(listOne: [1, 1, 2], listTwo: [0, 1, 1, 1, 2, 1, 2]))
38
+
39
+ }
40
+
41
+ func testSublistAtStart() {
42
+
43
+ XCTAssertEqual(.sublist, classifier(listOne: [0, 1, 2], listTwo: [0, 1, 2, 3, 4, 5]))
44
+ }
45
+
46
+ func testSublistInMiddle() {
47
+
48
+ XCTAssertEqual(.sublist, classifier(listOne: [2, 3, 4], listTwo: [0, 1, 2, 3, 4, 5]))
49
+
50
+ }
51
+
52
+ func testSublistAtEnd() {
53
+
54
+ XCTAssertEqual(.sublist, classifier(listOne: [3, 4, 5], listTwo: [0, 1, 2, 3, 4, 5]))
55
+
56
+ }
57
+
58
+ func testAtStartOfSuperList() {
59
+
60
+ XCTAssertEqual(.superlist, classifier(listOne: [0, 1, 2, 3, 4, 5], listTwo: [0, 1, 2]))
61
+
62
+ }
63
+
64
+ func testInMiddleOfSuperList() {
65
+
66
+ XCTAssertEqual(.superlist, classifier(listOne: [0, 1, 2, 3, 4, 5], listTwo: [2, 3]))
67
+ }
68
+
69
+ func testAtEndOfSuperList() {
70
+
71
+ XCTAssertEqual(.superlist, classifier(listOne: [0, 1, 2, 3, 4, 5], listTwo: [3, 4, 5]))
72
+ }
73
+
74
+ func testFirstListMissingElementFromSecondList() {
75
+
76
+ XCTAssertEqual(.unequal, classifier(listOne: [1, 3], listTwo: [1, 2, 3]))
77
+
78
+ }
79
+
80
+ func testSecondListMissingElementFromFirstList() {
81
+
82
+ XCTAssertEqual(.unequal, classifier(listOne: [1, 2, 3], listTwo: [1, 3]))
83
+ }
84
+
85
+ func testOrderMattersToAList() {
86
+
87
+ XCTAssertEqual(.unequal, classifier(listOne: [1, 2, 3], listTwo: [3, 2, 1]))
88
+
89
+ }
90
+
91
+ func testSameDigitsButDifferentNumbers() {
92
+
93
+ XCTAssertEqual(.unequal, classifier(listOne: [1, 0, 1], listTwo: [10, 1]))
94
+ }
95
+ }