1- //
2- // StrategyTests.swift
3- // DesignAlgorithmsKitTests
4- //
5- // Unit tests for Strategy Pattern
6- //
7-
81import XCTest
92@testable import DesignAlgorithmsKit
103
114final class StrategyTests : XCTestCase {
5+
6+ // MARK: - Basic Implementation
7+
128 func testStrategyPattern( ) {
139 // Given
1410 struct AdditionStrategy : Strategy {
1511 let strategyID = " addition "
16-
17- func execute( _ a: Int , _ b: Int ) -> Int {
18- return a + b
19- }
12+ func execute( _ a: Int , _ b: Int ) -> Int { return a + b }
2013 }
2114
2215 struct MultiplicationStrategy : Strategy {
2316 let strategyID = " multiplication "
24-
25- func execute( _ a: Int , _ b: Int ) -> Int {
26- return a * b
27- }
17+ func execute( _ a: Int , _ b: Int ) -> Int { return a * b }
2818 }
2919
3020 // When
@@ -39,92 +29,84 @@ final class StrategyTests: XCTestCase {
3929 XCTAssertEqual ( result2, 15 )
4030 }
4131
42- func testStrategyContext( ) {
43- // Given
44- struct TestStrategy : Strategy {
45- let strategyID = " test "
46- }
47-
48- // When
49- let context = StrategyContext ( strategy: TestStrategy ( ) )
50-
51- // Then
52- XCTAssertEqual ( context. getStrategy ( ) . strategyID, " test " )
53- }
54-
55- func testStrategyContextSetStrategy( ) {
32+ func testContextSwitching( ) {
5633 // Given
5734 struct TestStrategy : Strategy {
5835 let strategyID : String
36+ let val : Int
5937 }
6038
61- // When
62- let context = StrategyContext ( strategy: TestStrategy ( strategyID: " strategy1 " ) )
63- XCTAssertEqual ( context. getStrategy ( ) . strategyID, " strategy1 " )
39+ let s1 = TestStrategy ( strategyID: " s1 " , val: 1 )
40+ let s2 = TestStrategy ( strategyID: " s2 " , val: 2 )
6441
65- context. setStrategy ( TestStrategy ( strategyID: " strategy2 " ) )
42+ let context = StrategyContext ( strategy: s1)
43+ XCTAssertEqual ( context. getStrategy ( ) . val, 1 )
6644
67- // Then
68- XCTAssertEqual ( context. getStrategy ( ) . strategyID, " strategy2 " )
45+ context. setStrategy ( s2)
46+ XCTAssertEqual ( context. getStrategy ( ) . val, 2 )
47+
48+ context. setStrategy ( s1)
49+ XCTAssertEqual ( context. getStrategy ( ) . val, 1 )
6950 }
7051
52+ // MARK: - Inheritance and Types
53+
7154 func testBaseStrategy( ) {
72- // Given
7355 let baseStrategy = BaseStrategy ( strategyID: " base-test " )
74-
75- // Then
7656 XCTAssertEqual ( baseStrategy. strategyID, " base-test " )
7757 }
7858
7959 func testBaseStrategyInheritance( ) {
80- // Given
8160 class CustomStrategy : BaseStrategy {
82- init ( ) {
83- super. init ( strategyID: " custom " )
84- }
61+ init ( ) { super. init ( strategyID: " custom " ) }
62+ func op( ) -> String { return " op " }
8563 }
8664
87- // When
8865 let strategy = CustomStrategy ( )
89-
90- // Then
9166 XCTAssertEqual ( strategy. strategyID, " custom " )
67+ XCTAssertEqual ( strategy. op ( ) , " op " )
9268 }
9369
94- func testStrategyContextGetStrategy( ) {
95- // Given
96- struct TestStrategy : Strategy {
97- let strategyID = " test "
98- }
99-
100- let context = StrategyContext ( strategy: TestStrategy ( ) )
70+ // MARK: - Polymorphism
71+
72+ protocol MathStrategy : Strategy {
73+ func calculate( _ a: Int , _ b: Int ) -> Int
74+ }
75+
76+ struct Add : MathStrategy {
77+ var strategyID = " add "
78+ func calculate( _ a: Int , _ b: Int ) -> Int { a + b }
79+ }
80+
81+ struct Subtract : MathStrategy {
82+ var strategyID = " subtract "
83+ func calculate( _ a: Int , _ b: Int ) -> Int { a - b }
84+ }
85+
86+ func testPolymorphicContext( ) {
87+ let context = StrategyContext < BoxedMathStrategy > ( strategy: BoxedMathStrategy ( Add ( ) ) )
10188
102- // When
103- let retrievedStrategy = context. getStrategy ( )
89+ XCTAssertEqual ( context. getStrategy ( ) . calculate ( 10 , 5 ) , 15 )
10490
105- // Then
106- XCTAssertEqual ( retrievedStrategy . strategyID , " test " )
91+ context . setStrategy ( BoxedMathStrategy ( Subtract ( ) ) )
92+ XCTAssertEqual ( context . getStrategy ( ) . calculate ( 10 , 5 ) , 5 )
10793 }
10894
109- func testStrategyContextMultipleStrategies( ) {
110- // Given
111- struct TestStrategy : Strategy {
112- let strategyID : String
95+ // Type erasure wrapper for the test because StrategyContext is generic over a specific concrete type
96+ // or a protocol if used as an existentials (but StrategyContext<P> requires P: Strategy).
97+ // Protocols conforming to protocols don't satisfy P: Strategy for generic constraints in Swift
98+ // without `any` or box, testing here verifies the usage pattern.
99+ struct BoxedMathStrategy : MathStrategy {
100+ let strategyID : String
101+ private let _calculate : ( Int , Int ) -> Int
102+
103+ init < S: MathStrategy > ( _ strategy: S ) {
104+ self . strategyID = strategy. strategyID
105+ self . _calculate = strategy. calculate
113106 }
114107
115- // When
116- let context = StrategyContext ( strategy: TestStrategy ( strategyID: " strategy1 " ) )
117- context. setStrategy ( TestStrategy ( strategyID: " strategy2 " ) )
118-
119- // Then
120- XCTAssertEqual ( context. getStrategy ( ) . strategyID, " strategy2 " )
121- }
122- }
123-
124- // Extension to make strategies executable for testing
125- extension Strategy {
126- func execute( _ a: Int , _ b: Int ) -> Int {
127- return 0 // Default implementation
108+ func calculate( _ a: Int , _ b: Int ) -> Int {
109+ _calculate ( a, b)
110+ }
128111 }
129112}
130-
0 commit comments