Skip to content

Commit 63a7013

Browse files
authored
Merge pull request #11 from sassiwalid/10-migrate-to-swift-testing-framework
[Spark DI][Swift testing] - move to fully swift testing
2 parents e6a05e4 + 058d905 commit 63a7013

File tree

6 files changed

+23
-556
lines changed

6 files changed

+23
-556
lines changed

.github/workflows/ci.yml

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
name: CI
2-
32
on:
43
push:
54
branches:
@@ -10,22 +9,20 @@ on:
109

1110
jobs:
1211
build:
13-
runs-on: macOS-latest
14-
12+
runs-on: macos-14 # Use macOS 14 for Xcode 16 support
1513
steps:
16-
- name: Check Xcode Version
17-
run: xcodebuild -version
18-
1914
- name: Checkout code
20-
uses: actions/checkout@v2
21-
22-
- name: Set up Swift
23-
uses: fwal/setup-swift@v1
24-
with:
25-
swift-version: '5.9'
26-
15+
uses: actions/checkout@v4 # Updated to v4
16+
17+
- name: Select Xcode 16
18+
run: sudo xcode-select -s /Applications/Xcode_16.2.0.app/Contents/Developer
19+
20+
- name: Show Xcode and Swift Version
21+
run: xcodebuild -version
22+
swift --version
23+
2724
- name: Build SparkDI
28-
run: swift build
29-
30-
- name: Run Tests
31-
run: swift test
25+
run: swift build --build-tests
26+
27+
- name: Run Swift Testing Tests
28+
run: swift test --enable-code-coverage --parallel

Tests/SparkDITests/AssemblerTests.swift

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,10 @@
22
// Copyright © 2024 SparkDI Contributors. All rights reserved.
33
//
44

5-
#if canImport(Testing)
65
import Testing
7-
#endif
8-
import XCTest
6+
97
@testable import SparkDI
108

11-
#if canImport(Testing)
129
struct AssemblerTests {
1310
@Test func assemblerWithMultipleModules() async throws {
1411
/// GIVEN
@@ -39,32 +36,3 @@ struct AssemblerTests {
3936
#expect(userService1 !== userService2)
4037
}
4138
}
42-
#endif
43-
44-
final class AssemblerXCTests: XCTestCase {
45-
46-
func testAssemblerWithMultipleModules() async throws {
47-
let container = DependencyContainer()
48-
let assembler = Assembler(container: container)
49-
try await assembler.apply(
50-
modules: [NetworkModule(), UserModule()]
51-
)
52-
53-
// resolve Network module dependencies (singletons case)
54-
let apiService1 = try await container.resolve(type: APIServiceDummy.self)
55-
let apiService2 = try await container.resolve(type: APIServiceDummy.self)
56-
57-
let networkManager1 = try await container.resolve(type: NetworkManagerDummy.self)
58-
let networkManager2 = try await container.resolve(type: NetworkManagerDummy.self)
59-
60-
// resolve user module dependencies (new instance case)
61-
62-
let userService1 = try await container.resolve(type: UserServiceDummy.self)
63-
let userService2 = try await container.resolve(type: UserServiceDummy.self)
64-
65-
XCTAssertTrue(apiService1 === apiService2)
66-
XCTAssertTrue(networkManager1 === networkManager2)
67-
XCTAssertTrue(userService1 !== userService2)
68-
69-
}
70-
}

Tests/SparkDITests/ConcurrentTests.swift

Lines changed: 2 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@
22
// Copyright © 2024 SparkDI Contributors. All rights reserved.
33
//
44

5-
#if canImport(Testing)
65
import Testing
7-
#endif
8-
import XCTest
6+
import Foundation
7+
98
@testable import SparkDI
109

11-
#if canImport(Testing)
1210
struct SparkDIConcurrentTests {
1311
@Test
1412
func ConcurrentWriteCrash() async throws {
@@ -53,49 +51,3 @@ struct SparkDIConcurrentTests {
5351
}
5452
}
5553
}
56-
#endif
57-
58-
final class ConcurrentTests: XCTestCase {
59-
func testConcurrentWriteCrash() throws {
60-
let container = DependencyContainer()
61-
62-
let expectation = XCTestExpectation(description: "Concurrent writes should cause crash (1000 iterations)")
63-
64-
let iterations = 1000
65-
66-
DispatchQueue.concurrentPerform(iterations: iterations) { index in
67-
Task {
68-
try await container.register(
69-
type: String.self,
70-
factory: { _ in
71-
"instance \(index)"
72-
},
73-
scope: .transient
74-
)
75-
}
76-
}
77-
78-
expectation.fulfill()
79-
80-
wait(for: [expectation], timeout: 5)
81-
}
82-
83-
func testConcurrentReadCrash() throws {
84-
let container = DependencyContainer()
85-
86-
let expectation = XCTestExpectation(description: "Concurrent read should cause crash (1000 iterations)")
87-
88-
let iterations = 1000
89-
90-
DispatchQueue.concurrentPerform(iterations: iterations) { index in
91-
Task {
92-
_ = try await container.resolve(type: String.self)
93-
94-
}
95-
}
96-
97-
expectation.fulfill()
98-
99-
wait(for: [expectation], timeout: 5)
100-
}
101-
}
Lines changed: 2 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
//
22
// Copyright © 2024 SparkDI Contributors. All rights reserved.
33
//
4-
5-
#if canImport(Testing)
4+
import Foundation
65
import Testing
7-
#endif
8-
import XCTest
6+
97
@testable import SparkDI
108

11-
#if canImport(Testing)
129
struct DependencyInjectionTests {
1310

1411
@Test func singletonScopeWithoutParameter() async throws {
@@ -139,152 +136,3 @@ struct DependencyInjectionTests {
139136
}
140137

141138
}
142-
#endif
143-
144-
final class DependencyContainerTests: XCTestCase {
145-
146-
func testSingletonScopeWithoutParameter() async throws {
147-
/// Given
148-
let container = DependencyContainer()
149-
150-
/// When
151-
try await container.register(type: String.self, factory: { _ in "Singleton Instance" }, scope: .singleton)
152-
153-
// Then
154-
let instance1: String? = try await container.resolve(type: String.self)
155-
let instance2: String? = try await container.resolve(type: String.self)
156-
157-
XCTAssertTrue(
158-
instance1 == instance2,
159-
"Singleton scope should return the same instance"
160-
)
161-
162-
}
163-
164-
func testTransientScopeWithoutParameter() async throws {
165-
/// Given
166-
let container = DependencyContainer()
167-
168-
try await container.register(
169-
type: String.self,
170-
factory: { _ in UUID().uuidString
171-
},
172-
scope: .transient
173-
)
174-
175-
/// When
176-
177-
let instance1: String? = try await container.resolve(type: String.self)
178-
let instance2: String? = try await container.resolve(type: String.self)
179-
180-
/// Then
181-
182-
XCTAssertNotEqual(
183-
instance1,
184-
instance2,
185-
"Transient scope should create a new instance each time"
186-
)
187-
}
188-
189-
func testSingletonScopeWithSingleParameter() async throws {
190-
191-
/// Given
192-
let container = DependencyContainer()
193-
194-
try await container.register(
195-
type: AppConfigurationDummy.self,
196-
factory: { args in
197-
guard let version = args.first as? String else { fatalError("Invalid arguments") }
198-
199-
return AppConfigurationDummy(version: version)
200-
},
201-
scope: .singleton
202-
)
203-
204-
/// When
205-
206-
let instance1: AppConfigurationDummy? = try await container.resolve(
207-
type: AppConfigurationDummy.self,
208-
arguments: "1.0.0"
209-
)
210-
211-
let instance2: AppConfigurationDummy? = try await container.resolve(type: AppConfigurationDummy.self)
212-
213-
/// Then
214-
XCTAssertTrue(
215-
instance1 == instance2,
216-
"Singleton scope should return the same instance"
217-
)
218-
219-
}
220-
221-
func testTransientScopeWithSingleparameter() async throws {
222-
223-
/// Given
224-
let container = DependencyContainer()
225-
226-
try await container.register(
227-
type: AppConfigurationDummy.self,
228-
factory: { args in
229-
guard let version = args.first as? String else { fatalError("Invalid arguments") }
230-
231-
return AppConfigurationDummy(version: version)
232-
},
233-
scope: .transient
234-
)
235-
236-
/// When
237-
238-
let instance1: AppConfigurationDummy? = try await container.resolve(
239-
type: AppConfigurationDummy.self,
240-
arguments: "1.0.0"
241-
)
242-
243-
let instance2: AppConfigurationDummy? = try await container.resolve(
244-
type: AppConfigurationDummy.self,
245-
arguments: "2.0.0"
246-
)
247-
248-
/// Then
249-
250-
XCTAssertNotEqual(
251-
instance1,
252-
instance2,
253-
"Transient scope should create a new instance each time"
254-
)
255-
}
256-
257-
258-
func testTransientScopeWithMultipleParameters() async throws {
259-
/// Given
260-
let container = DependencyContainer()
261-
262-
try await container.register(
263-
type: String.self,
264-
factory: { args in
265-
guard let name = args[0] as? String, let age = args[1] as? Int else {
266-
return "Invalid arguments"
267-
}
268-
return "\(name) is \(age) years old"
269-
},
270-
scope: .transient
271-
)
272-
273-
/// When
274-
275-
let instance: String? = try await container.resolve(
276-
type: String.self,
277-
arguments: ["John", 25]
278-
)
279-
280-
/// Then
281-
282-
XCTAssertEqual(
283-
instance,
284-
"John is 25 years old"
285-
)
286-
}
287-
288-
}
289-
290-

0 commit comments

Comments
 (0)