在股票交易紀錄輸入 View 裡面,會需要一個轉換器,在畫面上的 property 按下新增後,進行輸入內容的檢查,以似 Data Model 的轉換。
規格
測試項目
開始 測試和實作
依前面所提步驟,先建立測試
import XCTest
@testable import TwStockTools
final class StockRecordUtilityTests: XCTestCase {
override func setUpWithError() throws {
}
override func tearDownWithError() throws {
}
func testCreateStockRecord() {
/// 這個 test 是可以在還沒寫實作前先寫的
/// 因為已經列出了測項,有測項就可以寫 test
let error = StockRecordUtility().getStockRecord(stockID: "", stockName: "", tradingSide: .buy, stockShares: "", stockCostPerShare: "")
/// 這邊的 Assert 也可以在還沒宣告對應的 Error 物件前先寫
XCTAssertEqual(erro, someError)
}
}
Step1: 開始實作 StockRecordUtility 物件
extension StockRecordUtility {
enum StockRecordInputError: Error {
case noValue
case castingError
}
}
struct StockRecordUtility {
func getStockRecord(stockID: String, stockName: String, tradingSide: StockTradingInputView.TradingSide, stockShares: String, stockCostPerShare: String) -> Result<StockTradingRecord, Error> {
/// 這還不是正式實作,需要寫 return 是為了讓 project 能 build 起來,只有能 build 後才能 testing
return .success(StockTradingRecord(stockID: "", stockName: "", tradingSide: .buy, tradingShares: 0, tradingAmount: 0))
}
}
step2: 修改 unit testing
import XCTest
@testable import TwStockTools
final class StockRecordUtilityTests: XCTestCase {
override func setUpWithError() throws {
}
override func tearDownWithError() throws {
}
func testCreateStockRecord() throws {
/// 這個 test 是可以在還沒寫實作前先寫的
/// 因為已經列出了測項,有測項就可以寫 test
let result = StockRecordUtility().getStockRecord(stockID: "", stockName: "", tradingSide: .buy, stockShares: "", stockCostPerShare: "")
switch result {
case .success(let _):
XCTFail("This test case not able success")
case .failure(let failure):
let error = try XCTUnwrap(failure as? StockRecordUtility.StockRecordInputError)
XCTAssertEqual(error, StockRecordUtility.StockRecordInputError.noValue)
}
}
}
step3: 跑測試
這一步一定失敗,因為我們預設空值時,return Result.Failure 且裡面為 Error 物件。
step4: 修改實作,讓這個 func 符合第一個 spe
func getStockRecord(stockID: String, stockName: String, tradingSide: StockTradingInputView.TradingSide, stockShares: String, stockCostPerShare: String) -> Result<StockTradingRecord, Error> {
if stockID.isEmpty ||
stockName.isEmpty ||
stockShares.isEmpty ||
stockCostPerShare.isEmpty {
return .failure(StockRecordInputError.noValue)
}
/// 這還不是正式實作,需要寫 return 是為了讓 project 能 build 起來,只有能 build 後才能 testing
return .success(StockTradingRecord(stockID: "", stockName: "", tradingSide: .buy, tradingShares: 0, tradingAmount: 0))
}
step5: 再跑一次測試,並確定通過