Skip to content

Instantly share code, notes, and snippets.

@kkebo
Last active October 24, 2023 15:13
Show Gist options
  • Save kkebo/29730032caa0ee4c4686497e987bb46f to your computer and use it in GitHub Desktop.
Save kkebo/29730032caa0ee4c4686497e987bb46f to your computer and use it in GitHub Desktop.
SwiftUI のプレビュー上でユニットテストを実行する Proof of Concept (ContentView のテストをしたい場合)
import SwiftUI
struct ContentView: View {
@State var hoge = 0
@Environment(\.testCaseNumber) private var testCaseNumber
func change() {
hoge = 3
}
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, world!")
}
.modifier(TestModifier(testCase: allTestCases[testCaseNumber]))
}
}
extension ContentView {
var allTestCases: [TestCase] {
[
test1,
test2,
]
}
var test1: TestCase {
.init(label: "hoge == 0") {
.init(success: hoge == 0)
}
}
var test2: TestCase {
.init(label: "hoge == 3") {
change()
return .init(success: hoge == 3)
}
}
}
#Preview {
VStack {
// FIXME: 個数はどこから持ってくる?
ForEach(0..<2, id: \.self) { i in
ContentView()
.environment(\.testCaseNumber, i)
}
}
.environment(\.isTesting, true)
}
struct TestCase: Identifiable {
var id: UUID = .init()
var label: String
var run: () -> TestResult
}
struct TestResult {
var success: Bool
}
struct IsTestingKey: EnvironmentKey {
static let defaultValue: Bool = false
}
extension EnvironmentValues {
var isTesting: Bool {
get { self[IsTestingKey.self] }
set { self[IsTestingKey.self] = newValue }
}
}
struct TestCaseNumberKey: EnvironmentKey {
static let defaultValue: Int = 0
}
extension EnvironmentValues {
var testCaseNumber: Int {
get { self[TestCaseNumberKey.self] }
set { self[TestCaseNumberKey.self] = newValue }
}
}
struct TestModifier: ViewModifier {
let testCase: TestCase
@Environment(\.isTesting) private var isTesting
@State private var result: TestResult?
func body(content: Content) -> some View {
if isTesting {
VStack {
if let result {
Text("\(testCase.label): \(result.success ? "passed" : "failed")")
} else {
Text("Running")
}
}
.onAppear {
result = testCase.run()
}
} else {
content
}
}
}
@kkebo
Copy link
Author

kkebo commented Oct 21, 2023

テストケース記述の自由度を上げようと思ったらもうちょっと考える必要あり

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment