From 38d0cbf85612a3d1ff466efd29d57cb3857c2618 Mon Sep 17 00:00:00 2001 From: meatball Date: Fri, 20 Dec 2024 19:46:37 +0100 Subject: [PATCH 1/2] Update Swift tools version to 6.0 and refactor test templates --- .../flatten-array/.meta/template.swift | 16 +- .../practice/flatten-array/Package.swift | 2 +- .../FlattenArrayTests/FlattenArrayTests.swift | 75 ++++----- .../practice/food-chain/.meta/template.swift | 16 +- exercises/practice/food-chain/Package.swift | 2 +- .../Tests/FoodChainTests/FoodChainTests.swift | 65 ++++---- .../practice/gigasecond/.meta/template.swift | 20 +-- exercises/practice/gigasecond/Package.swift | 2 +- .../GigasecondTests/GigasecondTests.swift | 61 ++++---- .../grade-school/.docs/instructions.md | 20 +-- .../GradeSchool/GradeSchoolExample.swift | 5 +- .../grade-school/.meta/template.swift | 22 +-- exercises/practice/grade-school/Package.swift | 2 +- .../GradeSchoolTests/GradeSchoolTests.swift | 143 +++++++++--------- 14 files changed, 236 insertions(+), 215 deletions(-) diff --git a/exercises/practice/flatten-array/.meta/template.swift b/exercises/practice/flatten-array/.meta/template.swift index a714fb157..098f80161 100644 --- a/exercises/practice/flatten-array/.meta/template.swift +++ b/exercises/practice/flatten-array/.meta/template.swift @@ -1,18 +1,20 @@ -import XCTest +import Testing +import Foundation @testable import {{exercise|camelCase}} -class {{exercise|camelCase}}Tests: XCTestCase { - let runAll = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false +let RUNALL = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false + +@Suite struct {{exercise|camelCase}}Tests { {% for case in cases %} {% if forloop.first -%} - func test{{case.description |camelCase }}() { + @Test("{{case.description}}") {% else -%} - func test{{case.description |camelCase }}() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("{{case.description}}", .enabled(if: RUNALL)) {% endif -%} + func test{{case.description |camelCase }}() { let result : [Int] = flattenArray({{case.input.array | toNilArray}}) let expected : [Int] = {{case.expected}} - XCTAssertEqual(expected, result) + #expect(expected == result) } {% endfor -%} } diff --git a/exercises/practice/flatten-array/Package.swift b/exercises/practice/flatten-array/Package.swift index a6634778f..dea1c8b05 100644 --- a/exercises/practice/flatten-array/Package.swift +++ b/exercises/practice/flatten-array/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.3 +// swift-tools-version:6.0 import PackageDescription diff --git a/exercises/practice/flatten-array/Tests/FlattenArrayTests/FlattenArrayTests.swift b/exercises/practice/flatten-array/Tests/FlattenArrayTests/FlattenArrayTests.swift index 7de69cf0b..815e9dd70 100644 --- a/exercises/practice/flatten-array/Tests/FlattenArrayTests/FlattenArrayTests.swift +++ b/exercises/practice/flatten-array/Tests/FlattenArrayTests/FlattenArrayTests.swift @@ -1,83 +1,90 @@ -import XCTest +import Foundation +import Testing @testable import FlattenArray -class FlattenArrayTests: XCTestCase { - let runAll = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false +let RUNALL = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false +@Suite struct FlattenArrayTests { + + @Test("empty") func testEmpty() { let result: [Int] = flattenArray([]) let expected: [Int] = [] - XCTAssertEqual(expected, result) + #expect(expected == result) } - func testNoNesting() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("no nesting", .enabled(if: RUNALL)) + func testNoNesting() { let result: [Int] = flattenArray([0, 1, 2]) let expected: [Int] = [0, 1, 2] - XCTAssertEqual(expected, result) + #expect(expected == result) } - func testFlattensANestedArray() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("flattens a nested array", .enabled(if: RUNALL)) + func testFlattensANestedArray() { let result: [Int] = flattenArray([[[]]]) let expected: [Int] = [] - XCTAssertEqual(expected, result) + #expect(expected == result) } - func testFlattensArrayWithJustIntegersPresent() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("flattens array with just integers present", .enabled(if: RUNALL)) + func testFlattensArrayWithJustIntegersPresent() { let result: [Int] = flattenArray([1, [2, 3, 4, 5, 6, 7], 8]) let expected: [Int] = [1, 2, 3, 4, 5, 6, 7, 8] - XCTAssertEqual(expected, result) + #expect(expected == result) } - func test5LevelNesting() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("5 level nesting", .enabled(if: RUNALL)) + func test5LevelNesting() { let result: [Int] = flattenArray([0, 2, [[2, 3], 8, 100, 4, [[[50]]]], -2]) let expected: [Int] = [0, 2, 2, 3, 8, 100, 4, 50, -2] - XCTAssertEqual(expected, result) + #expect(expected == result) } - func test6LevelNesting() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("6 level nesting", .enabled(if: RUNALL)) + func test6LevelNesting() { let result: [Int] = flattenArray([1, [2, [[3]], [4, [[5]]], 6, 7], 8]) let expected: [Int] = [1, 2, 3, 4, 5, 6, 7, 8] - XCTAssertEqual(expected, result) + #expect(expected == result) } - func testNullValuesAreOmittedFromTheFinalResult() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("null values are omitted from the final result", .enabled(if: RUNALL)) + func testNullValuesAreOmittedFromTheFinalResult() { let result: [Int] = flattenArray([1, 2, nil]) let expected: [Int] = [1, 2] - XCTAssertEqual(expected, result) + #expect(expected == result) } - func testConsecutiveNullValuesAtTheFrontOfTheListAreOmittedFromTheFinalResult() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test( + "consecutive null values at the front of the list are omitted from the final result", + .enabled(if: RUNALL)) + func testConsecutiveNullValuesAtTheFrontOfTheListAreOmittedFromTheFinalResult() { let result: [Int] = flattenArray([nil, nil, 3]) let expected: [Int] = [3] - XCTAssertEqual(expected, result) + #expect(expected == result) } - func testConsecutiveNullValuesInTheMiddleOfTheListAreOmittedFromTheFinalResult() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test( + "consecutive null values in the middle of the list are omitted from the final result", + .enabled(if: RUNALL)) + func testConsecutiveNullValuesInTheMiddleOfTheListAreOmittedFromTheFinalResult() { let result: [Int] = flattenArray([1, nil, nil, 4]) let expected: [Int] = [1, 4] - XCTAssertEqual(expected, result) + #expect(expected == result) } - func test6LevelNestListWithNullValues() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("6 level nest list with null values", .enabled(if: RUNALL)) + func test6LevelNestListWithNullValues() { let result: [Int] = flattenArray([0, 2, [[2, 3], 8, [[100]], nil, [[nil]]], -2]) let expected: [Int] = [0, 2, 2, 3, 8, 100, -2] - XCTAssertEqual(expected, result) + #expect(expected == result) } - func testAllValuesInNestedListAreNull() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("all values in nested list are null", .enabled(if: RUNALL)) + func testAllValuesInNestedListAreNull() { let result: [Int] = flattenArray([nil, [[[nil]]], nil, nil, [[nil, nil], nil], nil]) let expected: [Int] = [] - XCTAssertEqual(expected, result) + #expect(expected == result) } } diff --git a/exercises/practice/food-chain/.meta/template.swift b/exercises/practice/food-chain/.meta/template.swift index 5ec020358..f436b185a 100644 --- a/exercises/practice/food-chain/.meta/template.swift +++ b/exercises/practice/food-chain/.meta/template.swift @@ -1,17 +1,19 @@ -import XCTest +import Testing +import Foundation @testable import {{exercise|camelCase}} -class {{exercise|camelCase}}Tests: XCTestCase { - let runAll = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false +let RUNALL = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false + +@Suite struct {{exercise|camelCase}}Tests { {% for case in cases %} {% if forloop.first -%} - func test{{case.description |camelCase }}() { + @Test("{{case.description}}") {% else -%} - func test{{case.description |camelCase }}() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("{{case.description}}", .enabled(if: RUNALL)) {% endif -%} + func test{{case.description |camelCase }}() { let expected = "{{case.expected | join:"\n" + ""}}" - XCTAssertEqual(expected, FoodChain.song(start: {{case.input.startVerse}}, end: {{case.input.endVerse}})) + #expect(expected == FoodChain.song(start: {{case.input.startVerse}}, end: {{case.input.endVerse}})) } {% endfor -%} } diff --git a/exercises/practice/food-chain/Package.swift b/exercises/practice/food-chain/Package.swift index 16c2996b4..fbabb07ff 100644 --- a/exercises/practice/food-chain/Package.swift +++ b/exercises/practice/food-chain/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.3 +// swift-tools-version:6.0 import PackageDescription diff --git a/exercises/practice/food-chain/Tests/FoodChainTests/FoodChainTests.swift b/exercises/practice/food-chain/Tests/FoodChainTests/FoodChainTests.swift index c98408387..cea295695 100644 --- a/exercises/practice/food-chain/Tests/FoodChainTests/FoodChainTests.swift +++ b/exercises/practice/food-chain/Tests/FoodChainTests/FoodChainTests.swift @@ -1,61 +1,64 @@ -import XCTest +import Foundation +import Testing @testable import FoodChain -class FoodChainTests: XCTestCase { - let runAll = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false +let RUNALL = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "true"]) ?? false +@Suite struct FoodChainTests { + + @Test("fly") func testFly() { let expected = "I know an old lady who swallowed a fly.\n" + "I don't know why she swallowed the fly. Perhaps she'll die." - XCTAssertEqual(expected, FoodChain.song(start: 1, end: 1)) + #expect(expected == FoodChain.song(start: 1, end: 1)) } - func testSpider() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("spider", .enabled(if: RUNALL)) + func testSpider() { let expected = "I know an old lady who swallowed a spider.\n" + "It wriggled and jiggled and tickled inside her.\n" + "She swallowed the spider to catch the fly.\n" + "I don't know why she swallowed the fly. Perhaps she'll die." - XCTAssertEqual(expected, FoodChain.song(start: 2, end: 2)) + #expect(expected == FoodChain.song(start: 2, end: 2)) } - func testBird() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("bird", .enabled(if: RUNALL)) + func testBird() { let expected = "I know an old lady who swallowed a bird.\n" + "How absurd to swallow a bird!\n" + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n" + "She swallowed the spider to catch the fly.\n" + "I don't know why she swallowed the fly. Perhaps she'll die." - XCTAssertEqual(expected, FoodChain.song(start: 3, end: 3)) + #expect(expected == FoodChain.song(start: 3, end: 3)) } - func testCat() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("cat", .enabled(if: RUNALL)) + func testCat() { let expected = "I know an old lady who swallowed a cat.\n" + "Imagine that, to swallow a cat!\n" + "She swallowed the cat to catch the bird.\n" + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n" + "She swallowed the spider to catch the fly.\n" + "I don't know why she swallowed the fly. Perhaps she'll die." - XCTAssertEqual(expected, FoodChain.song(start: 4, end: 4)) + #expect(expected == FoodChain.song(start: 4, end: 4)) } - func testDog() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("dog", .enabled(if: RUNALL)) + func testDog() { let expected = "I know an old lady who swallowed a dog.\n" + "What a hog, to swallow a dog!\n" + "She swallowed the dog to catch the cat.\n" + "She swallowed the cat to catch the bird.\n" + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n" + "She swallowed the spider to catch the fly.\n" + "I don't know why she swallowed the fly. Perhaps she'll die." - XCTAssertEqual(expected, FoodChain.song(start: 5, end: 5)) + #expect(expected == FoodChain.song(start: 5, end: 5)) } - func testGoat() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("goat", .enabled(if: RUNALL)) + func testGoat() { let expected = "I know an old lady who swallowed a goat.\n" + "Just opened her throat and swallowed a goat!\n" @@ -64,11 +67,11 @@ class FoodChainTests: XCTestCase { + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n" + "She swallowed the spider to catch the fly.\n" + "I don't know why she swallowed the fly. Perhaps she'll die." - XCTAssertEqual(expected, FoodChain.song(start: 6, end: 6)) + #expect(expected == FoodChain.song(start: 6, end: 6)) } - func testCow() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("cow", .enabled(if: RUNALL)) + func testCow() { let expected = "I know an old lady who swallowed a cow.\n" + "I don't know how she swallowed a cow!\n" + "She swallowed the cow to catch the goat.\n" + "She swallowed the goat to catch the dog.\n" @@ -76,17 +79,17 @@ class FoodChainTests: XCTestCase { + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n" + "She swallowed the spider to catch the fly.\n" + "I don't know why she swallowed the fly. Perhaps she'll die." - XCTAssertEqual(expected, FoodChain.song(start: 7, end: 7)) + #expect(expected == FoodChain.song(start: 7, end: 7)) } - func testHorse() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("horse", .enabled(if: RUNALL)) + func testHorse() { let expected = "I know an old lady who swallowed a horse.\n" + "She's dead, of course!" - XCTAssertEqual(expected, FoodChain.song(start: 8, end: 8)) + #expect(expected == FoodChain.song(start: 8, end: 8)) } - func testMultipleVerses() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("multiple verses", .enabled(if: RUNALL)) + func testMultipleVerses() { let expected = "I know an old lady who swallowed a fly.\n" + "I don't know why she swallowed the fly. Perhaps she'll die.\n" + "\n" @@ -98,11 +101,11 @@ class FoodChainTests: XCTestCase { + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n" + "She swallowed the spider to catch the fly.\n" + "I don't know why she swallowed the fly. Perhaps she'll die." - XCTAssertEqual(expected, FoodChain.song(start: 1, end: 3)) + #expect(expected == FoodChain.song(start: 1, end: 3)) } - func testFullSong() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("full song", .enabled(if: RUNALL)) + func testFullSong() { let expected = "I know an old lady who swallowed a fly.\n" + "I don't know why she swallowed the fly. Perhaps she'll die.\n" + "\n" @@ -138,6 +141,6 @@ class FoodChainTests: XCTestCase { + "She swallowed the spider to catch the fly.\n" + "I don't know why she swallowed the fly. Perhaps she'll die.\n" + "\n" + "I know an old lady who swallowed a horse.\n" + "She's dead, of course!" - XCTAssertEqual(expected, FoodChain.song(start: 1, end: 8)) + #expect(expected == FoodChain.song(start: 1, end: 8)) } } diff --git a/exercises/practice/gigasecond/.meta/template.swift b/exercises/practice/gigasecond/.meta/template.swift index 13339b2dc..2d3aceafa 100644 --- a/exercises/practice/gigasecond/.meta/template.swift +++ b/exercises/practice/gigasecond/.meta/template.swift @@ -1,27 +1,29 @@ -import XCTest +import Testing +import Foundation @testable import {{exercise|camelCase}} -class {{exercise|camelCase}}Tests: XCTestCase { - let runAll = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false +let RUNALL = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false + +@Suite struct {{exercise|camelCase}}Tests { let dateFormatter = ISO8601DateFormatter() let dateTimeFormatter = ISO8601DateFormatter() - override func setUp() { + init() { dateFormatter.formatOptions = [.withFullDate] dateTimeFormatter.formatOptions = [.withFullDate, .withFullTime] } {% for case in cases %} {% if forloop.first -%} - func test{{case.description |camelCase }}() { + @Test("{{case.description}}") {% else -%} - func test{{case.description |camelCase }}() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("{{case.description}}", .enabled(if: RUNALL)) {% endif -%} + func test{{case.description |camelCase }}() { {%- if case.scenarios[0] == "date" -%} - XCTAssertEqual(gigasecond(from: dateFormatter.date(from: "{{case.input.moment}}")!), dateTimeFormatter.date(from: "{{case.expected}}Z")!) + #expect(gigasecond(from: dateFormatter.date(from: "{{case.input.moment}}")!) == dateTimeFormatter.date(from: "{{case.expected}}Z")!) {%- elif case.scenarios[0] == "datetime" -%} - XCTAssertEqual(gigasecond(from: dateTimeFormatter.date(from: "{{case.input.moment}}Z")!), dateTimeFormatter.date(from: "{{case.expected}}Z")!) + #expect(gigasecond(from: dateTimeFormatter.date(from: "{{case.input.moment}}Z")!) == dateTimeFormatter.date(from: "{{case.expected}}Z")!) {%- endif -%} } {% endfor -%} diff --git a/exercises/practice/gigasecond/Package.swift b/exercises/practice/gigasecond/Package.swift index 955c9a5c7..f1fba27fb 100644 --- a/exercises/practice/gigasecond/Package.swift +++ b/exercises/practice/gigasecond/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.3 +// swift-tools-version:6.0 import PackageDescription diff --git a/exercises/practice/gigasecond/Tests/GigasecondTests/GigasecondTests.swift b/exercises/practice/gigasecond/Tests/GigasecondTests/GigasecondTests.swift index 8e69ebb20..87abab7f8 100644 --- a/exercises/practice/gigasecond/Tests/GigasecondTests/GigasecondTests.swift +++ b/exercises/practice/gigasecond/Tests/GigasecondTests/GigasecondTests.swift @@ -1,53 +1,54 @@ -import XCTest +import Foundation +import Testing @testable import Gigasecond -class GigasecondTests: XCTestCase { - let runAll = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false +let RUNALL = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false +@Suite struct GigasecondTests { let dateFormatter = ISO8601DateFormatter() let dateTimeFormatter = ISO8601DateFormatter() - override func setUp() { + init() { dateFormatter.formatOptions = [.withFullDate] dateTimeFormatter.formatOptions = [.withFullDate, .withFullTime] } + @Test("date only specification of time") func testDateOnlySpecificationOfTime() { - XCTAssertEqual( - gigasecond(from: dateFormatter.date(from: "2011-04-25")!), - dateTimeFormatter.date(from: "2043-01-01T01:46:40Z")!) + #expect( + gigasecond(from: dateFormatter.date(from: "2011-04-25")!) == dateTimeFormatter.date( + from: "2043-01-01T01:46:40Z")!) } - func testSecondTestForDateOnlySpecificationOfTime() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test - XCTAssertEqual( - gigasecond(from: dateFormatter.date(from: "1977-06-13")!), - dateTimeFormatter.date(from: "2009-02-19T01:46:40Z")!) + @Test("second test for date only specification of time", .enabled(if: RUNALL)) + func testSecondTestForDateOnlySpecificationOfTime() { + #expect( + gigasecond(from: dateFormatter.date(from: "1977-06-13")!) == dateTimeFormatter.date( + from: "2009-02-19T01:46:40Z")!) } - func testThirdTestForDateOnlySpecificationOfTime() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test - XCTAssertEqual( - gigasecond(from: dateFormatter.date(from: "1959-07-19")!), - dateTimeFormatter.date(from: "1991-03-27T01:46:40Z")!) + @Test("third test for date only specification of time", .enabled(if: RUNALL)) + func testThirdTestForDateOnlySpecificationOfTime() { + #expect( + gigasecond(from: dateFormatter.date(from: "1959-07-19")!) == dateTimeFormatter.date( + from: "1991-03-27T01:46:40Z")!) } - func testFullTimeSpecified() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test - XCTAssertEqual( - gigasecond(from: dateTimeFormatter.date(from: "2015-01-24T22:00:00Z")!), - dateTimeFormatter.date(from: "2046-10-02T23:46:40Z")!) + @Test("full time specified", .enabled(if: RUNALL)) + func testFullTimeSpecified() { + #expect( + gigasecond(from: dateTimeFormatter.date(from: "2015-01-24T22:00:00Z")!) + == dateTimeFormatter.date(from: "2046-10-02T23:46:40Z")!) } - func testFullTimeWithDayRollOver() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test - XCTAssertEqual( - gigasecond(from: dateTimeFormatter.date(from: "2015-01-24T23:59:59Z")!), - dateTimeFormatter.date(from: "2046-10-03T01:46:39Z")!) + @Test("full time with day roll-over", .enabled(if: RUNALL)) + func testFullTimeWithDayRollOver() { + #expect( + gigasecond(from: dateTimeFormatter.date(from: "2015-01-24T23:59:59Z")!) + == dateTimeFormatter.date(from: "2046-10-03T01:46:39Z")!) } - func testDoesNotMutateTheInput() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test - } + @Test("does not mutate the input", .enabled(if: RUNALL)) + func testDoesNotMutateTheInput() {} } diff --git a/exercises/practice/grade-school/.docs/instructions.md b/exercises/practice/grade-school/.docs/instructions.md index 9a63e398d..3cb1b5d5f 100644 --- a/exercises/practice/grade-school/.docs/instructions.md +++ b/exercises/practice/grade-school/.docs/instructions.md @@ -1,21 +1,21 @@ # Instructions -Given students' names along with the grade that they are in, create a roster for the school. +Given students' names along with the grade they are in, create a roster for the school. In the end, you should be able to: -- Add a student's name to the roster for a grade +- Add a student's name to the roster for a grade: - "Add Jim to grade 2." - "OK." -- Get a list of all students enrolled in a grade +- Get a list of all students enrolled in a grade: - "Which students are in grade 2?" - - "We've only got Jim just now." + - "We've only got Jim right now." - Get a sorted list of all students in all grades. - Grades should sort as 1, 2, 3, etc., and students within a grade should be sorted alphabetically by name. - - "Who all is enrolled in school right now?" + Grades should be sorted as 1, 2, 3, etc., and students within a grade should be sorted alphabetically by name. + - "Who is enrolled in school right now?" - "Let me think. - We have Anna, Barb, and Charlie in grade 1, Alex, Peter, and Zoe in grade 2 and Jim in grade 5. - So the answer is: Anna, Barb, Charlie, Alex, Peter, Zoe and Jim" + We have Anna, Barb, and Charlie in grade 1, Alex, Peter, and Zoe in grade 2, and Jim in grade 5. + So the answer is: Anna, Barb, Charlie, Alex, Peter, Zoe, and Jim." -Note that all our students only have one name (It's a small town, what do you want?) and each student cannot be added more than once to a grade or the roster. -In fact, when a test attempts to add the same student more than once, your implementation should indicate that this is incorrect. +Note that all our students only have one name (it's a small town, what do you want?), and each student cannot be added more than once to a grade or the roster. +If a test attempts to add the same student more than once, your implementation should indicate that this is incorrect. diff --git a/exercises/practice/grade-school/.meta/Sources/GradeSchool/GradeSchoolExample.swift b/exercises/practice/grade-school/.meta/Sources/GradeSchool/GradeSchoolExample.swift index 2e7e1e884..f666eed35 100644 --- a/exercises/practice/grade-school/.meta/Sources/GradeSchool/GradeSchoolExample.swift +++ b/exercises/practice/grade-school/.meta/Sources/GradeSchool/GradeSchoolExample.swift @@ -1,7 +1,7 @@ -struct GradeSchool { +class GradeSchool { var rosters = [Int: [String]]() - mutating func addStudent(_ name: String, grade: Int) -> Bool { + func addStudent(_ name: String, grade: Int) -> Bool { if rosters.values.contains { $0.contains(name) } { return false } @@ -14,7 +14,6 @@ struct GradeSchool { } func roster() -> [String] { - print(rosters) return rosters.keys.sorted().flatMap { (rosters[$0] ?? [String]()).sorted() } } } diff --git a/exercises/practice/grade-school/.meta/template.swift b/exercises/practice/grade-school/.meta/template.swift index 56b2acda6..a6ea436fd 100644 --- a/exercises/practice/grade-school/.meta/template.swift +++ b/exercises/practice/grade-school/.meta/template.swift @@ -1,22 +1,24 @@ -import XCTest +import Testing +import Foundation @testable import {{exercise|camelCase}} -class {{exercise|camelCase}}Tests: XCTestCase { - let runAll = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false +let RUNALL = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false + +@Suite struct {{exercise|camelCase}}Tests { {% for case in cases %} {% if forloop.first -%} - func test{{case.description |camelCase }}() { + @Test("{{case.description}}") {% else -%} - func test{{case.description |camelCase }}() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("{{case.description}}", .enabled(if: RUNALL)) {% endif -%} + func test{{case.description |camelCase }}() { var school = GradeSchool() {%- if case.property == "add" %} {% for student in case.input.students -%} {%- if case.expected[forloop.counter0] %} - XCTAssertTrue(school.addStudent("{{student[0]}}", grade: {{student[1]}})) + #expect(school.addStudent("{{student[0]}}", grade: {{student[1]}})) {%- else %} - XCTAssertFalse(school.addStudent("{{student[0]}}", grade: {{student[1]}})) + #expect(!school.addStudent("{{student[0]}}", grade: {{student[1]}})) {%- endif -%} {% endfor %} {%- else %} @@ -24,9 +26,9 @@ class {{exercise|camelCase}}Tests: XCTestCase { school.addStudent("{{student[0]}}", grade: {{student[1]}}) {% endfor %} {%- if case.property == "roster" %} - XCTAssertEqual(school.roster(), {{case.expected | toStringArray}}) + #expect(school.roster() == {{case.expected | toStringArray}}) {%- elif case.property == "grade" %} - XCTAssertEqual(school.studentsInGrade({{case.input.desiredGrade}}), {{case.expected | toStringArray}}) + #expect(school.studentsInGrade({{case.input.desiredGrade}}) == {{case.expected | toStringArray}}) {%- endif %} {%- endif -%} } diff --git a/exercises/practice/grade-school/Package.swift b/exercises/practice/grade-school/Package.swift index fd39fa4bb..fe9e54c75 100644 --- a/exercises/practice/grade-school/Package.swift +++ b/exercises/practice/grade-school/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.3 +// swift-tools-version:6.0 import PackageDescription diff --git a/exercises/practice/grade-school/Tests/GradeSchoolTests/GradeSchoolTests.swift b/exercises/practice/grade-school/Tests/GradeSchoolTests/GradeSchoolTests.swift index eb59ac7fe..bae4f7124 100644 --- a/exercises/practice/grade-school/Tests/GradeSchoolTests/GradeSchoolTests.swift +++ b/exercises/practice/grade-school/Tests/GradeSchoolTests/GradeSchoolTests.swift @@ -1,131 +1,134 @@ -import XCTest +import Foundation +import Testing @testable import GradeSchool -class GradeSchoolTests: XCTestCase { - let runAll = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false +let RUNALL = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "true"]) ?? false +@Suite struct GradeSchoolTests { + + @Test("Roster is empty when no student is added") func testRosterIsEmptyWhenNoStudentIsAdded() { var school = GradeSchool() - XCTAssertEqual(school.roster(), []) + #expect(school.roster() == []) } - func testAddAStudent() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Add a student", .enabled(if: RUNALL)) + func testAddAStudent() { var school = GradeSchool() - XCTAssertTrue(school.addStudent("Aimee", grade: 2)) + #expect(school.addStudent("Aimee", grade: 2)) } - func testStudentIsAddedToTheRoster() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Student is added to the roster", .enabled(if: RUNALL)) + func testStudentIsAddedToTheRoster() { var school = GradeSchool() school.addStudent("Aimee", grade: 2) - XCTAssertEqual(school.roster(), ["Aimee"]) + #expect(school.roster() == ["Aimee"]) } - func testAddingMultipleStudentsInTheSameGradeInTheRoster() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Adding multiple students in the same grade in the roster", .enabled(if: RUNALL)) + func testAddingMultipleStudentsInTheSameGradeInTheRoster() { var school = GradeSchool() - XCTAssertTrue(school.addStudent("Blair", grade: 2)) - XCTAssertTrue(school.addStudent("James", grade: 2)) - XCTAssertTrue(school.addStudent("Paul", grade: 2)) + #expect(school.addStudent("Blair", grade: 2)) + #expect(school.addStudent("James", grade: 2)) + #expect(school.addStudent("Paul", grade: 2)) } - func testMultipleStudentsInTheSameGradeAreAddedToTheRoster() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Multiple students in the same grade are added to the roster", .enabled(if: RUNALL)) + func testMultipleStudentsInTheSameGradeAreAddedToTheRoster() { var school = GradeSchool() school.addStudent("Blair", grade: 2) school.addStudent("James", grade: 2) school.addStudent("Paul", grade: 2) - XCTAssertEqual(school.roster(), ["Blair", "James", "Paul"]) + #expect(school.roster() == ["Blair", "James", "Paul"]) } - func testCannotAddStudentToSameGradeInTheRosterMoreThanOnce() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Cannot add student to same grade in the roster more than once", .enabled(if: RUNALL)) + func testCannotAddStudentToSameGradeInTheRosterMoreThanOnce() { var school = GradeSchool() - XCTAssertTrue(school.addStudent("Blair", grade: 2)) - XCTAssertTrue(school.addStudent("James", grade: 2)) - XCTAssertFalse(school.addStudent("James", grade: 2)) - XCTAssertTrue(school.addStudent("Paul", grade: 2)) + #expect(school.addStudent("Blair", grade: 2)) + #expect(school.addStudent("James", grade: 2)) + #expect(!school.addStudent("James", grade: 2)) + #expect(school.addStudent("Paul", grade: 2)) } - func testStudentNotAddedToSameGradeInTheRosterMoreThanOnce() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Student not added to same grade in the roster more than once", .enabled(if: RUNALL)) + func testStudentNotAddedToSameGradeInTheRosterMoreThanOnce() { var school = GradeSchool() school.addStudent("Blair", grade: 2) school.addStudent("James", grade: 2) school.addStudent("James", grade: 2) school.addStudent("Paul", grade: 2) - XCTAssertEqual(school.roster(), ["Blair", "James", "Paul"]) + #expect(school.roster() == ["Blair", "James", "Paul"]) } - func testAddingStudentsInMultipleGrades() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Adding students in multiple grades", .enabled(if: RUNALL)) + func testAddingStudentsInMultipleGrades() { var school = GradeSchool() - XCTAssertTrue(school.addStudent("Chelsea", grade: 3)) - XCTAssertTrue(school.addStudent("Logan", grade: 7)) + #expect(school.addStudent("Chelsea", grade: 3)) + #expect(school.addStudent("Logan", grade: 7)) } - func testStudentsInMultipleGradesAreAddedToTheRoster() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Students in multiple grades are added to the roster", .enabled(if: RUNALL)) + func testStudentsInMultipleGradesAreAddedToTheRoster() { var school = GradeSchool() school.addStudent("Chelsea", grade: 3) school.addStudent("Logan", grade: 7) - XCTAssertEqual(school.roster(), ["Chelsea", "Logan"]) + #expect(school.roster() == ["Chelsea", "Logan"]) } - func testCannotAddSameStudentToMultipleGradesInTheRoster() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Cannot add same student to multiple grades in the roster", .enabled(if: RUNALL)) + func testCannotAddSameStudentToMultipleGradesInTheRoster() { var school = GradeSchool() - XCTAssertTrue(school.addStudent("Blair", grade: 2)) - XCTAssertTrue(school.addStudent("James", grade: 2)) - XCTAssertFalse(school.addStudent("James", grade: 3)) - XCTAssertTrue(school.addStudent("Paul", grade: 3)) + #expect(school.addStudent("Blair", grade: 2)) + #expect(school.addStudent("James", grade: 2)) + #expect(!school.addStudent("James", grade: 3)) + #expect(school.addStudent("Paul", grade: 3)) } - func testStudentNotAddedToMultipleGradesInTheRoster() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Student not added to multiple grades in the roster", .enabled(if: RUNALL)) + func testStudentNotAddedToMultipleGradesInTheRoster() { var school = GradeSchool() school.addStudent("Blair", grade: 2) school.addStudent("James", grade: 2) school.addStudent("James", grade: 3) school.addStudent("Paul", grade: 3) - XCTAssertEqual(school.roster(), ["Blair", "James", "Paul"]) + #expect(school.roster() == ["Blair", "James", "Paul"]) } - func testStudentsAreSortedByGradesInTheRoster() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Students are sorted by grades in the roster", .enabled(if: RUNALL)) + func testStudentsAreSortedByGradesInTheRoster() { var school = GradeSchool() school.addStudent("Jim", grade: 3) school.addStudent("Peter", grade: 2) school.addStudent("Anna", grade: 1) - XCTAssertEqual(school.roster(), ["Anna", "Peter", "Jim"]) + #expect(school.roster() == ["Anna", "Peter", "Jim"]) } - func testStudentsAreSortedByNameInTheRoster() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Students are sorted by name in the roster", .enabled(if: RUNALL)) + func testStudentsAreSortedByNameInTheRoster() { var school = GradeSchool() school.addStudent("Peter", grade: 2) school.addStudent("Zoe", grade: 2) school.addStudent("Alex", grade: 2) - XCTAssertEqual(school.roster(), ["Alex", "Peter", "Zoe"]) + #expect(school.roster() == ["Alex", "Peter", "Zoe"]) } - func testStudentsAreSortedByGradesAndThenByNameInTheRoster() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Students are sorted by grades and then by name in the roster", .enabled(if: RUNALL)) + func testStudentsAreSortedByGradesAndThenByNameInTheRoster() { var school = GradeSchool() school.addStudent("Peter", grade: 2) school.addStudent("Anna", grade: 1) @@ -135,67 +138,67 @@ class GradeSchoolTests: XCTestCase { school.addStudent("Jim", grade: 3) school.addStudent("Charlie", grade: 1) - XCTAssertEqual(school.roster(), ["Anna", "Barb", "Charlie", "Alex", "Peter", "Zoe", "Jim"]) + #expect(school.roster() == ["Anna", "Barb", "Charlie", "Alex", "Peter", "Zoe", "Jim"]) } - func testGradeIsEmptyIfNoStudentsInTheRoster() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Grade is empty if no students in the roster", .enabled(if: RUNALL)) + func testGradeIsEmptyIfNoStudentsInTheRoster() { var school = GradeSchool() - XCTAssertEqual(school.studentsInGrade(1), []) + #expect(school.studentsInGrade(1) == []) } - func testGradeIsEmptyIfNoStudentsInThatGrade() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Grade is empty if no students in that grade", .enabled(if: RUNALL)) + func testGradeIsEmptyIfNoStudentsInThatGrade() { var school = GradeSchool() school.addStudent("Peter", grade: 2) school.addStudent("Zoe", grade: 2) school.addStudent("Alex", grade: 2) school.addStudent("Jim", grade: 3) - XCTAssertEqual(school.studentsInGrade(1), []) + #expect(school.studentsInGrade(1) == []) } - func testStudentNotAddedToSameGradeMoreThanOnce() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Student not added to same grade more than once", .enabled(if: RUNALL)) + func testStudentNotAddedToSameGradeMoreThanOnce() { var school = GradeSchool() school.addStudent("Blair", grade: 2) school.addStudent("James", grade: 2) school.addStudent("James", grade: 2) school.addStudent("Paul", grade: 2) - XCTAssertEqual(school.studentsInGrade(2), ["Blair", "James", "Paul"]) + #expect(school.studentsInGrade(2) == ["Blair", "James", "Paul"]) } - func testStudentNotAddedToMultipleGrades() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Student not added to multiple grades", .enabled(if: RUNALL)) + func testStudentNotAddedToMultipleGrades() { var school = GradeSchool() school.addStudent("Blair", grade: 2) school.addStudent("James", grade: 2) school.addStudent("James", grade: 3) school.addStudent("Paul", grade: 3) - XCTAssertEqual(school.studentsInGrade(2), ["Blair", "James"]) + #expect(school.studentsInGrade(2) == ["Blair", "James"]) } - func testStudentNotAddedToOtherGradeForMultipleGrades() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Student not added to other grade for multiple grades", .enabled(if: RUNALL)) + func testStudentNotAddedToOtherGradeForMultipleGrades() { var school = GradeSchool() school.addStudent("Blair", grade: 2) school.addStudent("James", grade: 2) school.addStudent("James", grade: 3) school.addStudent("Paul", grade: 3) - XCTAssertEqual(school.studentsInGrade(3), ["Paul"]) + #expect(school.studentsInGrade(3) == ["Paul"]) } - func testStudentsAreSortedByNameInAGrade() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Students are sorted by name in a grade", .enabled(if: RUNALL)) + func testStudentsAreSortedByNameInAGrade() { var school = GradeSchool() school.addStudent("Franklin", grade: 5) school.addStudent("Bradley", grade: 5) school.addStudent("Jeff", grade: 1) - XCTAssertEqual(school.studentsInGrade(5), ["Bradley", "Franklin"]) + #expect(school.studentsInGrade(5) == ["Bradley", "Franklin"]) } } From fb9f1927b1add615f722afe95cf46bea25505ee5 Mon Sep 17 00:00:00 2001 From: meatball Date: Fri, 3 Jan 2025 23:27:59 +0100 Subject: [PATCH 2/2] Re-generate test files --- .../food-chain/Tests/FoodChainTests/FoodChainTests.swift | 2 +- .../grade-school/Tests/GradeSchoolTests/GradeSchoolTests.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/practice/food-chain/Tests/FoodChainTests/FoodChainTests.swift b/exercises/practice/food-chain/Tests/FoodChainTests/FoodChainTests.swift index cea295695..a1d843c52 100644 --- a/exercises/practice/food-chain/Tests/FoodChainTests/FoodChainTests.swift +++ b/exercises/practice/food-chain/Tests/FoodChainTests/FoodChainTests.swift @@ -3,7 +3,7 @@ import Testing @testable import FoodChain -let RUNALL = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "true"]) ?? false +let RUNALL = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false @Suite struct FoodChainTests { diff --git a/exercises/practice/grade-school/Tests/GradeSchoolTests/GradeSchoolTests.swift b/exercises/practice/grade-school/Tests/GradeSchoolTests/GradeSchoolTests.swift index bae4f7124..3dca674eb 100644 --- a/exercises/practice/grade-school/Tests/GradeSchoolTests/GradeSchoolTests.swift +++ b/exercises/practice/grade-school/Tests/GradeSchoolTests/GradeSchoolTests.swift @@ -3,7 +3,7 @@ import Testing @testable import GradeSchool -let RUNALL = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "true"]) ?? false +let RUNALL = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false @Suite struct GradeSchoolTests {