Last active
April 11, 2021 00:42
-
-
Save yosshi4486/6cea0bef05aae8f22fd6edc1f3e91b94 to your computer and use it in GitHub Desktop.
テストターゲットとメインターゲットの両方から読み込んでテスト環境値の注入を行うフレームワークのファイルサンプル
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// .gitignoreで該当のtestEnvironmentBackingStore.jsonファイルだけ取り除いておくようにする。 | |
// ProcessInfoを使わずに値をメインターゲットに渡したかったので考えてみた。各種設定項目をいじることで流用可能。 | |
// これをProcessInfoの代わりに、TestEnvironment.sharedとして値を取り出すようにすれば、ちょっとマシになるかなと。 | |
// フレームワーク自体にアプリケーションのテストに関する知識が書き込まれているので、OSS化は難しい? | |
// 参考にしたのはSKTestSessionの設計 | |
// | |
// TestEnvironment.swift | |
// BulistsTestEnvironment | |
// | |
// Created by yosshi4486 on 2021/04/10. | |
// | |
import Foundation | |
#if TEST | |
/// シミュレートしたいエラーを列挙する | |
public enum TestEnvironmentErrorCode: Int, Codable { | |
case `default` | |
public var error: Error { | |
switch self { | |
case .default: | |
return NSError(domain: "UITest", code: 1, userInfo: [ | |
NSLocalizedDescriptionKey: "UI Test Error", | |
NSLocalizedFailureReasonErrorKey: "An Error is occured from UITest.", | |
NSLocalizedRecoverySuggestionErrorKey: "Nothing.", | |
]) | |
} | |
} | |
} | |
public struct TestSettings: Codable { | |
/// NSManagedObjectContextの保存を実行した際にエラーを発生させるかどうかのBool値. デフォルトはfalse | |
public var saveErrorEnabled: Bool = false | |
/// `saveErrorEnabled`によって起こった保存エラーで投げるエラーの種類, デフォルトはUIエラー | |
public var saveErrorCode: TestEnvironmentErrorCode = .default | |
/// NSPersistentContainerの読み込みを実行した際にエラーを発生させるかどうかのBool値. デフォルトはfalse | |
public var loadErrorEnabled: Bool = false | |
/// `loadErrorEnabled`によって起こった読み込みエラーで投げるエラーの種類。デフォルトはUIエラー | |
public var loadErrorCode: TestEnvironmentErrorCode = .default | |
/// `XCUIApplication().launch`の際にローカルストレージのデータを削除するかどうかのBool値. デフォルトはfalse. | |
public var clearPersistedDataOnLaunch: Bool = false | |
/// `XCUIApplication().launch`の際に初期データを何件投入するかの整数. デフォルトは0件 | |
public var numberOfAddDataOnLaunch: Int = 0 | |
} | |
/// テスト設定をテストターゲットから操作して、アプリケーションターゲットで読み込ませるための環境 | |
@dynamicMemberLookup public final class TestEnvironment { | |
/// テスト環境は1つしか存在しない | |
public static let shared = TestEnvironment() | |
public subscript<U>(dynamicMember keyPath: WritableKeyPath<TestSettings, U>) -> U { | |
get { | |
loadFromBackingStore() | |
return settings[keyPath:keyPath] | |
} | |
set { | |
settings[keyPath:keyPath] = newValue | |
saveToBackingStore() | |
} | |
} | |
/// TestSettingsをjsonにエンコードするエンコーダー | |
private let jsonEncoder = JSONEncoder() | |
/// 保存されたjsonをTestSettingsにデコードするデコーダー | |
private let jsonDecoder = JSONDecoder() | |
/// 設定用のファイルを保存/読み出しするパス | |
/// | |
/// gitignoreでこのパスをignoreしており差分は出ないようになっている。あくまでソースディレクトリ内に追加でファイルを作成して操作しているため | |
/// CIでもコケることはない | |
let backingStoreJSONFilePath = URL(fileURLWithPath: #file) | |
.deletingLastPathComponent() | |
.appendingPathComponent("testEnvironmentBackingStore.json") | |
/// 読み書きする設定のキャッシュ | |
private var settings: TestSettings = .init() | |
private init() { | |
loadFromBackingStore() | |
} | |
deinit { | |
resetToBaseStates() | |
saveToBackingStore() | |
} | |
/// 設定した変数を初期値にリセットする. | |
public func resetToBaseStates() { | |
settings = .init() | |
saveToBackingStore() | |
} | |
private func loadFromBackingStore() { | |
if let data = try? Data(contentsOf: backingStoreJSONFilePath), let settings = try? jsonDecoder.decode(TestSettings.self, from: data) { | |
self.settings = settings | |
} else { | |
// 存在しない場合は初期データを投入する。 | |
saveToBackingStore() | |
} | |
} | |
private func saveToBackingStore() { | |
let encoded = try! jsonEncoder.encode(settings) | |
try! encoded.write(to: backingStoreJSONFilePath, options: .atomicWrite) | |
} | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment