#swift #xctest #xcode-ui-testing #xctestcase #xctestexpectation
#swift #xctest #xcode-ui-testing #xctestcase #xctestexpectation
Вопрос:
Предыстория
Следующие тесты вызывают метод, который является расширением XCTestCase. Цель:
waitForElementExists
Метод возвращает, потому что элемент существует илиwaitForElementExists
Метод завершает работу с ошибкой вызвавшего его тестового примера / метода установки, поскольку элемент не существовал в течение указанного времени
Расширение XCTestCase для автоматизации пользовательского интерфейса для ожидания метода:
extension XCTestCase
{
/**
Wait for the view to load
Note: Must be a part of XCTestCase in order to utilize expectationForPredicate and waitForExpectationsWithTimeout
- Parameter
- element: The XCUIElement representing the view
- timeout: The NSTimeInterval for how long you want to wait for the view to be loaded
- file: The file where this method was called
- line: The line where this method was called
*/
func waitForElementExists(element: XCUIElement, timeout: NSTimeInterval = 60,
file: String = #file, line: UInt = #line)
{
let exists = NSPredicate(format: "exists == true")
expectationForPredicate(exists, evaluatedWithObject: element, handler: nil)
waitForExpectationsWithTimeout(timeout) { (error) -> Void in
if (error != nil)
{
let message = "Failed to find (element) after (timeout) seconds."
self.recordFailureWithDescription(message,
inFile: file, atLine: line, expected: true)
}
}
}
}
Пример, в котором waitForExpectationsWithTimeout работает правильно
Тестовый пример
override func setUp()
{
super.setUp()
// Stop immediately when a failure occurs.
continueAfterFailure = false
XCUIApplication().launch()
waitForElementExists(XCUIApplication().buttons["Foo"])
}
func testSample()
{
print("Success")
}
Это работает! testSample
никогда не вызывается.
Но что, если мы переместим вызов waitForElementExists во вспомогательный метод?
Пример, в котором waitForExpectationsWithTimeout возвращается успешно, но не должен
Здесь тестовый пример продолжается, как будто утверждение никогда не выполнялось. Если я ввожу точку останова в waitForElementExists
, я вижу, что continueAfterFailure
для нее установлено значение true, поэтому ясно, что она не подключена к тому же коду, что и основной тестовый пример.
Тестовый пример
lazy var SomeHelper = SomeHelperClass()
override func setUp()
{
super.setUp()
// Stop immediately when a failure occurs.
continueAfterFailure = false
XCUIApplication().launch()
SomeHelper.waitForReady()
}
func testSample()
{
print("Success")
}
Вспомогательный файл
class SomeHelperClass: XCTestCase
{
/**
Wait for the button to be loaded
*/
func waitForReady()
{
waitForElementExists(XCUIApplication().buttons["Foo"])
}
}
Ответ №1:
Поскольку ваш вспомогательный класс относится к подклассам XCTestCase, у него есть собственное continueAfterFailure
свойство, которое по умолчанию равно true.
Если вам нужен вспомогательный класс, он не должен происходить от XCTestCase, поскольку подклассы XCTestCase должны реализовывать методы тестирования. Если вам нужно получить доступ к функциональности из вашего расширения XCTestCase в вашем вспомогательном классе, передайте объект вашего тестового примера по композиции при создании вашего вспомогательного класса.
class SomeHelper {
let testCase: XCTestCase
init(for testCase: XCTestCase) {
self.testCase = testCase
}
func await(_ element: XCUIElement) {
testCase.waitForElementExists(element)
}
}
class MyTests: XCTestCase {
let app = XCUIApplication()
var helper: SomeHelper!
func setUp() {
continueAfterFailure = false
helper = SomeHelper(for: self)
helper.await(app.buttons["foo"])
}
}