Для моего нового приложения Swiftui я хочу добавить тесты. Используя Swift Testing, я начал писать некоторые модульные тесты. Я также хочу добавить тесты пользовательского интерфейса. Приложение в значительной степени зависит от сетевых вызовов для извлечения данных для отображения и выполнения действий. Состояние также важно, приложение можно использовать только в том случае, если пользователь вошел в систему, например. Используя некоторые онлайн -уроки, я добавил простой тест пользовательского интерфейса, который открывает приложение и входит в систему в пользователе. Этот тест фактически запускает приложение, выполняя вход в систему, связавшись с фактическим сервером аутентификации. Чтобы проверить другие представления, это должно быть сделано каждый раз, прежде чем запустить фактический тест для тестирования конкретного представления. Видно, что он рекомендуется использовать протоколы для просмотров, используемых представлениями, и создания фиктивной версии, чтобы предварительные просмотра работали. Это предпочтительный способ издеваться над запросами сети и утверждать тесты xctest пользовательского интерфейса? Если это так, то как эти макет должны быть введены, поскольку тесты пользовательского интерфейса, кажется, запускают все приложение, а не конкретные представления.let app = XCUIApplication()
app.launch()
Структура приложения
Ниже приведен упрощенный пример структуры моего приложения. Для моих тестов я хотел бы издеваться над состоянием isauthenticated в AuthenticationModel и высмеивать сетевые вызовы, либо в AuthenticationModel , либо в Apiclient .
На основании комментариев и ответов до сих пор я получаю впечатление, что я должен, по крайней мере, рефактор AuthenticationModel и ApiClient . Apiclient должен быть зависимостью аутентификации, моделя и должна быть введена через конструктор AuthenticationModel , чтобы его можно было высмеивать.
import SwiftUI
struct ContentView: View {
@EnvironmentObject var authModel: AuthenticationModel
var body: some View {
if authModel.isAuthenticated {
VStack {
Text("Welcome \(authModel.username)")
Button {
Task {
await authModel.logout()
}
} label: {
Text("Logout")
}
.buttonStyle(.borderedProminent)
}
.padding()
} else {
VStack {
TextField("Username", text: $authModel.username)
.multilineTextAlignment(.center)
TextField("Password", text: $authModel.password)
.multilineTextAlignment(.center)
Button {
Task {
await authModel.login()
}
} label: {
Text("Login")
}
.buttonStyle(.borderedProminent)
}
.padding()
}
}
}
#Preview {
let authModel = AuthenticationModel()
ContentView().environmentObject(authModel)
}
< /code>
import Foundation
class AuthenticationModel: ObservableObject {
@Published var isAuthenticated = false
@Published var username = ""
@Published var password = ""
func login() async {
if !username.isEmpty && !password.isEmpty {
await APIClient().postRequest(
with: URL(string: "www.example.com/login")!,
andBody: LoginRequest(username: username, password: password))
isAuthenticated = true
}
}
func logout() async {
username = ""
password = ""
isAuthenticated = false
}
}
< /code>
import Foundation
struct APIClient {
func getRequest(with url: URL) async -> T? {
return nil
}
func postRequest(with url: URL, andBody body: T) async {
}
}
struct LoginRequest: Encodable {
let username: String
let password: String
}
< /code>
import SwiftUI
@main
struct MockTestsApp: App {
@StateObject private var authModel = AuthenticationModel()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(authModel)
}
}
}
test ui test
Пример базового теста пользовательского интерфейса, в котором пользователь входит в систему. Для этого теста я бы я нравится издеваться над запросом входа в систему, чтобы тест не зависел от внешнего сервера аутентификации. Кроме того, я хочу написать тест, где пользователь уже входит в систему, чтобы я мог проверить пользовательские интерфейсы, которые доступны только для регистрации в пользователях без необходимости выполнения входа в систему для каждого из этих тестов. < /P>
< Pre Class = "Lang-Swift PrettyPrint-Override">import XCTest
final class MockTestsUITests: XCTestCase {
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
// In UI tests it is usually best to stop immediately when a failure occurs.
continueAfterFailure = false
// In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
}
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
@MainActor
func testLogin() throws {
let app = XCUIApplication()
app.launch()
app.textFields["Username"].tap()
app.textFields["Username"].typeText("Example")
app.textFields["Password"].tap()
app.textFields["Password"].typeText("Password")
app.buttons["Login"].tap()
XCUIApplication().staticTexts["Welcome Example"].tap()
// This test works, but I'd like to mock the login request somehow. With the current test implementation the test is dependent on a server to perform an actual login.
}
@MainActor
func testOtherFunctionality() throws {
// Mock the authentication state so a login doesn't have to be performed by this test
// Test actual other functionality
}
@MainActor
func testLaunchPerformance() throws {
if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
// This measures how long it takes to launch your application.
measure(metrics: [XCTApplicationLaunchMetric()]) {
XCUIApplication().launch()
}
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/794 ... ing-xctest
Как издеваться от ответов сети и состояния тестов пользовательского интерфейса с использованием xctest? ⇐ IOS
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение