Skip to content

Commit

Permalink
Add initial test cases (#38)
Browse files Browse the repository at this point in the history
* Add initial test case

* Add a negative test case

* Back to Dependency Client style

* Move mock to test

* Update MyLibrary/Sources/ScheduleFeature/Schedule.swift

Co-authored-by: Daiki Matsudate <[email protected]>

* Remove testValue = Self()

* Create struct for response

---------

Co-authored-by: Daiki Matsudate <[email protected]>
  • Loading branch information
kvvzr and d-date committed Mar 18, 2024
1 parent a6c36d2 commit eef1a4d
Show file tree
Hide file tree
Showing 8 changed files with 205 additions and 20 deletions.
2 changes: 2 additions & 0 deletions App/App.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
2435021A2BA49F29000083BB /* App.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = App.xctestplan; sourceTree = "<group>"; };
D563615B2B931FF800E4F789 /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; };
D563615E2B931FF800E4F789 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
D56361642B931FF900E4F789 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
Expand Down Expand Up @@ -106,6 +107,7 @@
D56361662B931FF900E4F789 /* App.entitlements */,
D563616A2B931FF900E4F789 /* Info.plist */,
D583D7C12B9AD2ED00B94F73 /* PrivacyInfo.xcprivacy */,
2435021A2BA49F29000083BB /* App.xctestplan */,
D56361672B931FF900E4F789 /* Preview Content */,
);
path = App;
Expand Down
9 changes: 7 additions & 2 deletions App/App.xcodeproj/xcshareddata/xcschemes/App.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,13 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
shouldUseLaunchSchemeArgsEnv = "YES">
<TestPlans>
<TestPlanReference
reference = "container:App/App.xctestplan"
default = "YES">
</TestPlanReference>
</TestPlans>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
Expand Down
29 changes: 29 additions & 0 deletions App/App/App.xctestplan
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"configurations" : [
{
"id" : "235E58B3-6724-418C-907A-6211C4CC541B",
"name" : "Test Scheme Action",
"options" : {

}
}
],
"defaultOptions" : {
"codeCoverage" : false,
"targetForVariableExpansion" : {
"containerPath" : "container:App.xcodeproj",
"identifier" : "D563615A2B931FF800E4F789",
"name" : "App"
}
},
"testTargets" : [
{
"target" : {
"containerPath" : "container:..\/MyLibrary",
"identifier" : "ScheduleFeatureTests",
"name" : "ScheduleFeatureTests"
}
}
],
"version" : 1
}
7 changes: 7 additions & 0 deletions MyLibrary/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,12 @@ let package = Package(
.plugin(name: "LicenseProviderPlugin", package: "LicenseProvider")
]
),
.testTarget(
name: "ScheduleFeatureTests",
dependencies: [
"ScheduleFeature",
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
]
),
]
)
30 changes: 25 additions & 5 deletions MyLibrary/Sources/ScheduleFeature/Schedule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ public struct Schedule {
var id: Self { self }
}

public struct SchedulesResponse: Equatable {
var day1: Conference
var day2: Conference
var workshop: Conference
}

@ObservableState
public struct State: Equatable {

Expand All @@ -29,7 +35,7 @@ public struct Schedule {
@Presents var destination: Destination.State?

public init() {
try! Tips.configure([.displayFrequency(.immediate)])
try? Tips.configure([.displayFrequency(.immediate)])
}
}

Expand All @@ -38,6 +44,7 @@ public struct Schedule {
case path(StackAction<Path.State, Path.Action>)
case destination(PresentationAction<Destination.Action>)
case view(View)
case fetchResponse(Result<SchedulesResponse, Error>)

public enum View {
case onAppear
Expand Down Expand Up @@ -66,10 +73,12 @@ public struct Schedule {
Reduce { state, action in
switch action {
case .view(.onAppear):
state.day1 = try! dataClient.fetchDay1()
state.day2 = try! dataClient.fetchDay2()
state.workshop = try! dataClient.fetchWorkshop()
return .none
return .send(.fetchResponse(Result {
let day1 = try dataClient.fetchDay1()
let day2 = try dataClient.fetchDay2()
let workshop = try dataClient.fetchWorkshop()
return .init(day1: day1, day2: day2, workshop: workshop)
}))
case let .view(.disclosureTapped(session)):
guard let description = session.description, let speakers = session.speakers else {
return .none
Expand All @@ -93,6 +102,17 @@ public struct Schedule {
#elseif os(visionOS)
return .run { _ in await openURL(url) }
#endif
case let .fetchResponse(.success(response)):
state.day1 = response.day1
state.day2 = response.day2
state.workshop = response.workshop
return .none
case let .fetchResponse(.failure(error as DecodingError)):
assertionFailure(error.localizedDescription)
return .none
case let .fetchResponse(.failure(error)):
print(error) // TODO: replace to Logger API
return .none
case .binding, .path, .destination:
return .none
}
Expand Down
13 changes: 0 additions & 13 deletions MyLibrary/Tests/MyLibraryTests/MyLibraryTests.swift

This file was deleted.

97 changes: 97 additions & 0 deletions MyLibrary/Tests/ScheduleFeatureTests/Mocks.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import Foundation
import SharedModels

extension Conference {
static let mock1 = Self(
id: 1,
title: "conference1",
date: Date(timeIntervalSince1970: 1_000),
schedules: [
.init(
time: Date(timeIntervalSince1970: 10_000),
sessions: [
.mock1,
.mock2,
]
)
]
)

static let mock2 = Self(
id: 2,
title: "conference2",
date: Date(timeIntervalSince1970: 2_000),
schedules: [
.init(
time: Date(timeIntervalSince1970: 20_000),
sessions: [
.mock1,
.mock2
]
)
]
)

static let mock3 = Self(
id: 3,
title: "conference3",
date: Date(timeIntervalSince1970: 3_000),
schedules: [
.init(
time: Date(timeIntervalSince1970: 30_000),
sessions: [
.mock1,
.mock2
]
)
]
)
}

extension Session {
static let mock1 = Self(
title: "session1",
speakers: [
.mock1
],
place: "place1",
description: "description1",
requirements: "requirements1"
)

static let mock2 = Self(
title: "session2",
speakers: [
.mock2
],
place: "place2",
description: "description2",
requirements: "requirements2"
)
}

extension Speaker {
static let mock1 = Self(
name: "speaker1",
imageName: "image1",
bio: "bio1",
links: [
.init(
name: "sns1",
url: URL(string: "https://example.com/speaker1")!
)
]
)

static let mock2 = Self(
name: "speaker2",
imageName: "image2",
bio: "bio2",
links: [
.init(
name: "sns2",
url: URL(string: "https://example.com/speaker2")!
)
]
)
}
38 changes: 38 additions & 0 deletions MyLibrary/Tests/ScheduleFeatureTests/ScheduleTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import ComposableArchitecture
import DataClient
import XCTest

@testable import ScheduleFeature

final class ScheduleTests: XCTestCase {
@MainActor
func testFetchData() async {
let store = TestStore(initialState: Schedule.State()) {
Schedule()
} withDependencies: {
$0[DataClient.self].fetchDay1 = { @Sendable in .mock1 }
$0[DataClient.self].fetchDay2 = { @Sendable in .mock2 }
$0[DataClient.self].fetchWorkshop = { @Sendable in .mock3 }
}
await store.send(.view(.onAppear))
await store.receive(\.fetchResponse.success) {
$0.day1 = .mock1
$0.day2 = .mock2
$0.workshop = .mock3
}
}

@MainActor
func testFetchDataFailure() async {
struct FetchError: Equatable, Error {}
let store = TestStore(initialState: Schedule.State()) {
Schedule()
} withDependencies: {
$0[DataClient.self].fetchDay1 = { @Sendable in throw FetchError() }
$0[DataClient.self].fetchDay2 = { @Sendable in .mock2 }
$0[DataClient.self].fetchWorkshop = { @Sendable in .mock3 }
}
await store.send(.view(.onAppear))
await store.receive(\.fetchResponse.failure)
}
}

0 comments on commit eef1a4d

Please sign in to comment.