Update the CHANGELOG.md with the description of the changes between the last released version and the new one
日本語の概要は準備中です。原文の説明を表示しています。
Migrate the XCTests unit tests of a spark-ios-component-XXX (or common/theming) to Swift Testing, folder by folder, without adding or removing tests.
日本語の概要は準備中です。原文の説明を表示しています。
実行スコア 未検証
インストール方法を見るインストールする前に、エージェントに与えられる指示の中身を確認できます。
This skill migrates the unit tests (Tests/UnitTests) written with XCTest to Swift Testing.
/spark-replace-xctests button):
Modules/Components/{component-name}/.func test_xxx() becomes exactly one @Test function, with the same GIVEN / WHEN / THEN logic and the same assertions.@Test("Purpose of the test"). The name is a short readable sentence describing what is tested (e.g. @Test("Setup should call all use cases")).struct annotated with @Suite("Component Xxx Tests") (e.g. @Suite("SegmentedControl Item ViewModel Tests")).test_ prefix (e.g. test_setup_shouldCallUseCases -> setupShouldCallUseCases).// MARK: - structure of the file.@_spi(SI_SPI) and @testable imports, replace import XCTest by import Testing.Tests/SnapshotTests): they are already on Swift Testing.| XCTest | Swift Testing |
|---|---|
final class XxxTests: XCTestCase | @Suite("...") struct XxxTests |
override func setUp() | init() (or a local Stub) |
XCTAssertEqual(a, b, "msg") | #expect(a == b, "msg") |
XCTAssertNotEqual(a, b) | #expect(a != b) |
XCTAssertTrue(a) / XCTAssertFalse(a) | #expect(a) / #expect(!a) |
XCTAssertNil(a) / XCTAssertNotNil(a) | #expect(a == nil) / #expect(a != nil) |
XCTAssertIdentical(a, b) | #expect(a === b) |
XCTUnwrap(a) | try #require(a) |
XCTFail("msg") | Issue.record("msg") |
XxxMockTest.XCTAssert(...) | XxxMockTest.expect(...) |
XxxMockTest.XCTCalled(...) / not called helpers | XxxMockTest.expectCalled(...) |
file: StaticString = #filePath, line: UInt = #line | sourceLocation: Testing.SourceLocation = #_sourceLocation |
for case in Xxx.allCases { ... } (when only to iterate) | keep the loop (do not convert to arguments, it would change the number of tests) |
Run sourcery first (cd Modules/Components/{component-name} && sourcery) to be sure the MockTest helpers with expect are generated.
Migrate step by step, folder by folder, in this order, and build/run the tests after each folder before moving to the next:
AccessibilityIdentifierConstantsEnumModelTokenEnvironmentUseCaseViewModelFor each folder:
grep -rl "XCTestCase" Tests/UnitTests/<Folder>).func test before, @Test( after).swiftlint at the root of the module.The ViewModel tests are the most complex. Keep the current structure of the existing test file (same tests, same Stub, same helpers) and adapt it to the reference:
Modules/Components/SegmentedControl/Tests/UnitTests/ViewModel/SegmentedControlItemViewModelTests.swift
Expected structure:
import Testing
@testable import SparkComponentXxx
@_spi(SI_SPI) @testable import SparkComponentXxxTesting
@_spi(SI_SPI) import SparkThemingTesting
@_spi(SI_SPI) import SparkTheming
@_spi(SI_SPI) import SparkCommonTesting
@Suite("Xxx ViewModel Tests")
struct XxxViewModelTests {
// MARK: - Initialization
@Test("Initialization should use default values")
func initializationShouldUseDefaultValues() {
// GIVEN / WHEN
let stub = Stub()
let viewModel = stub.viewModel
// THEN
expectEqualToExpected(on: stub, otherColors: XxxColors())
expectNotCalled(on: stub, getColorsUseCase: true)
}
// MARK: - Setup
@Test("Setup should call all use cases")
func setupShouldCallAllUseCases() {
// GIVEN
let stub = Stub()
let viewModel = stub.viewModel
// WHEN
viewModel.setup(stub: stub)
// THEN
expectEqualToExpected(on: stub)
XxxGetColorsUseCaseableMockTest.expect(
stub.getColorsUseCaseMock,
expectedNumberOfCalls: 1,
givenTheme: stub.givenTheme,
expectedReturnValue: stub.expectedColors
)
}
// MARK: - Property Changes
// ...
}
// MARK: - Stub
private final class Stub {
// given values, expected values, use case mocks, viewModel, init(), resetMockedData()
}
// MARK: - Extension
private extension XxxViewModel {
func setup(stub: Stub) { ... }
}
// MARK: - Expectations
private func expectNotCalled(
on stub: Stub,
getColorsUseCase: Bool = false,
sourceLocation: Testing.SourceLocation = #_sourceLocation
) {
XxxGetColorsUseCaseableMockTest.expectCalled(
stub.getColorsUseCaseMock,
executeWithThemeCalled: !getColorsUseCase,
sourceLocation: sourceLocation
)
}
private func expectEqualToExpected(
on stub: Stub,
otherColors: XxxColors? = nil,
sourceLocation: Testing.SourceLocation = #_sourceLocation
) {
#expect(
stub.viewModel.colors == (otherColors ?? stub.expectedColors),
"Wrong colors value",
sourceLocation: sourceLocation
)
}
ViewModel specific rules:
private final class Stub (no inheritance from an XCTest stub base class). If the existing stub uses Combine publishers (PublisherMock, sink), keep the same logic.XCTAssert... helper functions (XCTAssertNotCalled, XCTAssertEqualToExpected, ...) become expectNotCalled, expectEqualToExpected, ... with a sourceLocation parameter forwarded to every #expect / MockTest.expect... call.@MainActor, annotate the suite with @MainActor.まだレビューはありません。使ってみた感想をお寄せください。
ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。
まだコメントはありません。最初のコメントを書いてみませんか。
Update the CHANGELOG.md with the description of the changes between the last released version and the new one
日本語の概要は準備中です。原文の説明を表示しています。
Launch some action before create push in git
日本語の概要は準備中です。原文の説明を表示しています。
Create or update a accessibility identifier file in the AccessibilityIdentifier folder in Sources of a spark-ios-component-XXX and add or update unit tests.
日本語の概要は準備中です。原文の説明を表示しています。
Create or update a constants file in the Constants folder in Sources of a spark-ios-component-XXX and add or update unit tests.
日本語の概要は準備中です。原文の説明を表示しています。
Create or update the DocC documentation in Sources of a spark-ios-component-XXX.
日本語の概要は準備中です。原文の説明を表示しています。
Create or update an enum file in the Enum folder in Sources of a spark-ios-component-XXX and add or update unit tests.
日本語の概要は準備中です。原文の説明を表示しています。