12/08/2018, 15:34

Giới thiệu về UI Testing trong iOS

UITesting là gì? UI testing là một phương thức test thông qua giao diện người dùng (User Interface). Khái niệm này không có gì xa lạ cả, chúng ta vẫn thường xuyên thực hiện UI Testing một cách thủ công, bằng cách chạy app và dùng tay nhấn vào các đối tượng như buttong, textfield, tableview,... ...

UITesting là gì?

UI testing là một phương thức test thông qua giao diện người dùng (User Interface). Khái niệm này không có gì xa lạ cả, chúng ta vẫn thường xuyên thực hiện UI Testing một cách thủ công, bằng cách chạy app và dùng tay nhấn vào các đối tượng như buttong, textfield, tableview,... trên app. Tuy nhiên phương thức test thủ công như cách chúng ta vẫn làm không phải là một cách làm hay. Bạn có thể nhớ và test lại một số chức năng mà bạn nghi ngờ rằng phần bạn sửa trước đó sẽ làm ảnh hưởng; tuy nhiên bạn sẽ bỏ qua một số chức năng mà mà bạn cho rằng không bị ảnh hưởng. Hơn nữa để lặp đi lặp lại hành động test các chức năng trên giao diện này đôi khi khá mất thời gian. Vậy tại sao không để máy tính làm thay mình, trong khi ngồi nhâm nhi tách cà phê nhỉ. Vâng, đó chính là lý do UI Testing ra đời.

Trong bài viết trước tôi đã đề cập đến Unit Testing , đây là một phương thức test tương đối đơn giản, chỉ thao tác trên một đơn vị nhỏ (function, class), để nhằm đảm bảo xem nó có hoạt động đúng một chức năng nhất định nào không.

UI Testing không đơn giản như vậy, việc bạn cần làm là giả như có một người dùng đang sử dụng ứng dụng bằng cách nhấn, rê ngón tay, kéo thả trên giao diện của app; và ứng dụng của bạn sẽ phản hồi lại các thao tác ấy như thế nào, có giống như bạn mong đợi hay không.

Tại sao chúng ta nên viết UI Test

Có một số lý do mà chúng ta nên sử dụng UI test như sau:

  • Nhằm giảm thiểu tình trạng bug đã fix rồi lại quay trở lại Trên thực tế, đây là lợi ích chung mà hầu hết tất cả các phương thức Automation testing đem lại, không riêng gì UI Testing. Khi chúng ta tiến hành chỉnh sửa bất cứ thứ gì, thì việc test lại là cần thiết, để đảm bảo chúng ta không làm hỏng một chỗ nào đó, và ứng dụng vẫn hoạt động như mong muốn.

cả khi chỉ có những thay đổi dù rất nhỏ, nhưng nếu không được test lại cũng sẽ rất nguy hiểm, lập trình viên sẽ phải tiến hành rất nhiều bước test thủ công để đảm bảo app đang hoạt động đúng. Đôi khi cả team QC cũng sẽ phải ngồi lại, chia từng phần nhỏ để cùng nhau test lại chức năng của app. Nhưng với UI Testing của Xcode, chúng ta không cần phải như làm như vậy nữa,. UI Test sẽ giúp chúng ta làm hầu hết các thao tác test một cách khá tốt.

Nói vậy không có nghĩa là chúng ta sẽ phó thác hoàn toàn vào công cụ UI Testing này. Luôn có những phần mà phương thức test này không thể thay thế phương thứ test thủ công. Tuy nhiên khi có nó, thời gian chúng ta phải bỏ ra để test thủ công sẽ được rút ngắn.

  • Giúp hỗ trợ test các View Controller Về lý thuyết, chúng ta vẫn có thể sử dụng Unit test để test các chức năng liên quan đến UI (User Interface). Tuy nhiên, với UI Testing, mọi việc sẽ đơn giản hơn nhiều. UI Test sẽ đóng vai trò như một người dùng thực sự, không cần quan tâm đến logic bên dưới của ứng dụng, cái mà nó muốn và thao tác trực tiếp chính là các đối tượng trên giao diện app

  • Có tác dụng như là một toài lài liệu của ứng dụng. Nhìn vào đoạn code sau:

func testWrongUsernameOrPassword() {
  fillInUsername()
  fillInWrongPassword()
  tapButton("Login")
  expectToSeeAlert("Username or password is incorrect")
  tapButton("OK")
}

Đây là một function của UI Test với kịch bản là người dùng cố gắng đăng nhập với username và password không chính xác. Nhìn vào đoạn code trên bất kỳ ai (hiểu tiếng Anh) cũng có thể hiểu được một cách dễ dàng.

Vì thế, chúng ta có thể nhanh chóng nắm bắt được cách làm việc của app, bằng cách nhìn vào các hàm test, đó thực sự là những tài liệu tuyệt vời cho một dự án.

  • Đem lại trải nghiệm trực quan khi sử dụng app Như đã nói ở trên, giống như chúng ta đang nhìn một nguwoif dùng đang thao tác trên app của mình vậy, thực sự hết sức thú vị.

Bước đầu tiên chúng ta tạo một ứng dụng, tiến hành đặt tên và tích vào check box chọn Include UI Tests XCode sẽ sinh ra thêm 1 target dành cho UI Testing.

Trong trường hợp bạn đã có một project, tuy nhiên trước đó bạn chưa chọn "Include UI Tests" thì bây giờ bạn có thể thêm vào bằng cách tạo một target mới. Như bạn thấy, may mắn thay, cuối cùng từ Xcode 7 trở đi đã có một mục dành riêng cho Test target

Target bạn tạo có thể là Objective-C hoặc Swift. Sẽ có một số đoạn code mẫu được tự động sinh ra, nhưng chúng ta có thể tự tạo bằng cách nhấn vào button Record. "Recording" là một chức năng hết sức thú vị của Xcode 7, nó sẽ tự động viết hầu hết tất các các đoạn code của UI Testing thay chúng ta. Đơn giản, chỉ cần đặt con trỏ chuột vào một hàm test() { ... } bất kì, sau đó nhấn nút Record, và tiến hành sử dụng app, bạn sẽ thấy các dòng code được tự động sinh ra. Giống như sau:

Trong app demo này, kịch bản test sẽ là: Khi nhấn vào button Hello, thì một Alert sẽ hiện ra. Đoạn code được Xcode sinh ra sẽ có dạng như sau:

testSayHello() {
  let app = XCUIApplication()
  app.buttons["say hello"].tap()
  app.alerts["Hello"].collectionViews.buttons["Dismiss"].tap()
}

Chúng ta có thể thấy, đoạn code trên trông thật tường minh và dễ hiểu. Và nếu chạy đoạn code test này, chúng ta sẽ thấy output trong Console như sau:

Test Case '-[BenchUITests.BenchUITests testSayHello]' started.
2015-06-15 19:36:13.494 XCTRunner[3123:9611325] Continuing to run tests in the background with task ID 1
  t =     1.60s     Wait for app to idle
  t =     1.81s     Tap the "say hello" Button
  t =     1.81s         Wait for app to idle
  t =     1.81s         Find the "say hello" Button
  t =     1.84s         Dispatch the event
  t =     2.08s         Wait for app to idle
  t =     2.10s     Tap the "Dismiss" Button
  t =     2.10s         Wait for app to idle
  t =     2.56s         Find the "Dismiss" Button
  t =     2.57s         Dispatch the event
  t =     2.81s         Wait for app to idle
Test Case '-[BenchUITests.BenchUITests testSayHello]' passed (3.215 seconds).

Đoạn output trên cho ta biết được đoạn code test thực hiện các hành động gì trên UI, và thời gian thực hiện của mỗi thao tác. Bạn cũng có thể nhấn vào biểu tượng Inspector để xem trạng thái fail của test case

Asserting the app state

Kịch bản test tiếp theo mà chúng ta cùng xem xét đó là "Khi tap vào nút Show Elements, chúng ta sẽ thấy list các Elements". Đoạn code sinh ra khi chúng ta nhấn Record và thao tác app sẽ có dạng như sau:

func testShowElements() {
  let app = XCUIApplication()
  app.buttons["show elements"].tap()
  app.tables.staticTexts["[N] Nitrogen (7)"].swipeUp()
  app.tables.staticTexts["[Ir] Iridium (77)"].swipeUp()
  app.tables.staticTexts["[Tl] Thallium (81)"].swipeUp()
  app.tables.staticTexts["[Uut] Ununtrium (113)"].swipeUp()
}

Sau khi bạn cuộn xuống cuối cùng của tableview, bạn có thể thấy có rất nhiều đoạn code giống nhau bị lặp, điều này thực sự không cần thiết, vì vậy chúng ta cần phải viết lại chúng. Đoạn code bắt đầu không có gì thay đổi, đơn giản vẫn là lick vào button "show elements" để load màn hình tiếp theo:

let app = XCUIApplication()

XCUIApplication là đối tượng đại diện cho việc app đang được chạy, và từ nó chúng ta có thể có các truy vấn (query) đê tương tác đến giao diện của app, như sau:

app.buttons["show elements"].tap()

Phương thức .buttons["show elements"] được gọi là một XCUIElementQuery được cung cấp bởi một đối tượng có kiểu XCUIApplication. Phương thức này sẽ thất bại nếu trong app không có bất kì button nào có tên "show elements". Ngược lại nếu có một butotn như vậy, phương thức trên sẽ trả về một đối tượng XCUIElement đại diện cho một button. Chúng ta có thể giả lập tao tác tap vào button đó thông qua phương thức .tap().

XCUIApplication, XCUIElementQuery, and XCUIElement là ba đối tượng không thể thiếu của UI Testing. Bước sau đây là để đảm bảo rằng màn hình tiếp theo đang hiển thị chỉ duy nhất một table:

XCTAssertEqual(app.tables.count, 1)

Bạn có thể thấy đây là một API thương được dùng trong XCTest, điều đó có nghĩa là chúng ta có thể dễ dàng kết hợp các API của XCTest và UITest. Sau khi đảm bảo được rằng chỉ có duy nhất một bảng, chúng ta cần đảm bảo rằng số lượng phần tử của bảng ấy giống như chúng ta mong đợi, ví dụ ở đây là 118 phần tử:

let table = app.tables.elementAtIndex(0)
XCTAssertEqual(table.cells.count, 118)

Đoạn code test của chúng ta sẽ như sau:

func testShowElements() {
  let app = XCUIApplication()
  app.buttons["show elements"].tap()

  XCTAssertEqual(app.tables.count, 1)

  let table = app.tables.elementAtIndex(0)
  let expectedNumberOfElements: UInt = 118
  XCTAssertEqual(table.cells.count, expectedNumberOfElements)
}

Trên đây chúng ta đã có được một cái nhìn cơ bản về UI Testing lần đầu tiên xuất hiện trên Xcode 7 cũng như những thức mà UI Test có thể làm được.

http://www.mokacoding.com/blog/xcode-7-ui-testing/ https://www.bignerdranch.com/blog/ui-testing-in-xcode-7-part-1-ui-testing-gotchas/ https://www.appcoda.com/automated-ui-test/

0