1. Giới thiệu về Geb

  • Geb là một framework trình duyệt tự động viết dựa trên ngôn ngữ Groovy.

  • Geb tập hợp sức mạnh của WebDriver, sự sang trọng của lựa chọn nội dung jQuery, sự vững mạnh của mô hình trang Object và biểu cảm của ngôn ngữ Groovy.

  • Geb có thể được sử dụng cho script và tự động hóa chung, hoặc giống như là một giải pháp cho functional/web testing thông qua việc tích hợp với các framework như Spock, JUnit & TestNG.

  • Bản chất của ngôn ngữ Groovy là tự nhiên gần gũi đối tượng nên lượng code sử dụng trong Geb framework sử dụng ít hơn các framework khác.

  • Có nhiều trình duyệt hỗ trợ Geb như: ChromeDriver, InternetExplorerDriver, FirefoxDriver, OperaDriver… Ngoài ra Geb còn dùng được trên các hệ điều hành như Windows hay IOS hoặc Android.

  • Geb sử dụng sức mạnh của Selenium WebDriver.

  • WebDriver là công cụ để viết auto test cho web.Mục đích của nó là mô phỏng các thao tác của người dùng và giao tiếp với HTML của ứng dụng.

  • WebDriver là một phần của Selenium.

  • Selenium là công cụ giả lập action trên browser, bắt chước y hệt thao tác của user và ko loại trừ bất cứ hạn chế nào.

  • Geb cung cấp jQuery giống như API cho lựa chọn nội dung web.

  • jQuery là 1 thư viện định nghĩa sẵn các phương thức javascript giúp viết code javascript nhanh hơn, đơn giản hơn.

  • jQuery cũng là một file js thông thường, do đó cần nhúng thư viện jquery lên web trước khi bắt tay vào làm.

2. Ưu điểm & nhược điểm của Geb

2.1 Ưu điểm của Geb

  • Loại bỏ việc kiểm tra bằng tay nhàm chán.

  • Phù hợp cho các dự án lớn với nhiều trường hợp thử nghiệm.

  • Unit test không đủ để bắt lỗi.

  • Tích hợp hệ thống phức tạp.

  • Sử dụng tích hợp được với nhiều framework test như JUnit, testNG, Spock.

  • Geb dễ dàng tích hợp với các tool build như Gradle, Grails và Maven.

  • Có thể dùng mô hình M-V-C (Model-View-Control).

  • Data access Obiects – lấy thông tin khách hàng.

  • Tiết kiệm thời gian và tiền bạc.

  • Tăng tốc mở nhiều trang.

  • Giảm việc nhập dữ liệu.

  • Việc kiểm tra bằng tay mất năm phút thì Geb có thể làm trong vài giây.

  • Không quá khó để tìm hiểu (ngôn ngữ dễ dọc, dễ học).

2.2 Nhược điểm của Geb

  • Không có nhiều hữu ích với các dự án nhỏ

    • Sử dụng Geb có thể mất nhiều thời gian hơn so với việc không dùng.

    • So với việc dùng Geb thì test thủ công có thể đã đáp ứng đủ.

  • Geb khá cầu kì về môi trường ứng dụng trang web (chỉ trong môi trường Grails, Maven, Gradle).

  • Geb yêu cầu phải có chu trình học tập (phải mất công sức và thời gian để nghiên cứu, tìm hiểu ngôn ngữ, cài đặt, cách sử dụng).

  • Hỗ trợ test mobile nhưng chỉ là giả lập.

3. Những điều kiện cần khi sử dụng Geb

3.1 Cài đặt JDK

  • Trên môi trường Ubuntu

    • Bước 1: Cài đặt JDK

      $ sudo apt-get install openjdk-7-jdk

    • Bước 2: Kiểm tra version java vừa cài đặt

      $ java -version

  • Trên môi trường Windows

3.2 Cài đặt Eclipse

  • Cả trên môi trường Windows và Ubuntu

    • Bước 1: Download Eclipse từ link

      http://www.eclipse.org/downloads/

    • Bước 2: Giải nén

    • Bước 3: Chạy file eclipse.exe trong thư mục eclipse để khởi động eclipse

3.3 Cài đặt Maven

4. Sử dụng Geb

4.1 Cách sử dụng Geb

4.1.1 Tạo mới một project

  • Bước 1: Tạo mới một project Groovy trên eclipse

    • Trên Menu của Eclipse vào File/new/Other, Eclipse mở ra cửa sổ:

    1.jpg

    • Chọn Groovy /Groovy Project, kích nút Next và Finish để hoàn thiện một Project Groovy. Groovy Project tạo ra như hình:

    2.jpg

  • Bước 2: Convert Groovy Project sang Maven Project

    • Kích chuột phải vào tên project groovy vừa tạo ra vào chọn chức năng Configure/Convert to Maven Project

      3.jpeg

4.1.2 Mô tả các file cấu hình

  • Cấu hình file pom

    • Mục đích: file pom sẽ quản lý các thư viện cần sử dụng trong project, khi cần sử dụng thư viện nào ta chỉ cần khai báo thêm vào file pom và phải đảm bảo các thư viện được add thêm vào là đồng bộ với nhau.

    • Nội dung của một file pom.xml khi mới khởi tạo các bạn có thể tham khảo trên mạng

    http://www.omniprogrammer.com/?p=222

  • Cấu hình file pom.xml

    • Các <dependency> sử dụng: nơi khai báo các thư viện sử dụng trong dự án.

    • Một số <dependency> được sử dụng là:

      Thư viện cho Junit phiên bản 0.10.0

      Thư viện cho Spock phiên bản 1.0-groovy-2.3

      Thư viện Geb cho Spock

      Thư viện sử dụng trình duyệt Firefox

      Thư viện sử dụng trình duyệt IE

      Thư viện sử dụng trình duyệt Chrome

      Thư viện để get element trong Selenium

      Thư viên để điều khiển trình duyệt trong Selenium

  • Cấu hình file GebConfig.groovy

    • Mục đích: Chúng ta sẽ sử dụng file cấu hình này để kiểm soát các thiết lập hoặc cấu hình cho toàn project hoặc những cấu hình cần thiết để giao tiếp với công cụ bên ngoài.

    • Một số cấu hình trong file GebConfig.groovy như:

      Cấu hình chạy trên các trình duyệt như Firefox, Chrome, IE…

      Cấu hình proxy

      Cấu hình PhantomJS

4.1.3 Geb power

  • Script Geb sử dụng các lệnh điều khiển của Groovy:

    • To: tới page browser được chỉ định

    • Content: mô tả các thành phần của trang

    • Required: yêu cầu trả về hoặc không trả về content

    • Cache: có lưu cache hay không mỗi lần Content được request. Cache giúp cho việc test chạy nhanh hơn

    • Wait: chờ Content trả về

    • Page: cho phép định nghĩa một frame page

4.2 Các công cụ cơ bản của Geb

4.2.1 Browser/Driver

  • Browser: Dùng để khởi tạo một test browser mới

    • Phương thức khai báo:
import geb.Browser

          import org.openqa.selenium.firefox.FirefoxDriver

          def browser = new Browser()

          browser.driver = new FirefoxDriver()
 * Hoặc:
import geb.Browser

          import org.openqa.selenium.firefox.FirefoxDriver

          def browser = new Browser(driver: new FirefoxDriver())
  • Driver()method: cho phép rút ngắn câu lệnh trong khi viết script

    • Ví dụ:
Browser.drive {

               go "signup"

               $("h1").text() == "Signup Page"

             }
  => Tương đương với viết script theo cách sau:
def browser = new Browser()

          browser.go "signup"

          browser.$("h1").text() == "Signup Page"

4.2.2 Pages

  • Page Object: Mỗi Page object là một test page, trong đó định nghĩa tất cả các phần tử cần kiểm tra của trang.

    • Cấu trúc khai báo: class SignupPage extends Page {}

    • Khai báo các thành phần trong page:

      URL:
      
static url = "https://www.facebook.com/"
       Title:
static at = { title == "Facebook" }
       Content: khai báo các phần tử của trang, sử dụng phương thức `$()` để lấy ra các phần tử cần kiểm tra.
static content = {

           title {$("title")}

           facebookLoginBtn {$("li.facebook")}

           loginForm { $("form") }

           username { $("input[name=email]") }

           password { $("input[name=password]") }

           submitButton{ loginForm.find("input", id: "login") }

          }
* Gọi khởi tạo trang và hiển thị trang đó bằng phương thức `to()` hoặc `via()`

    `to()`: mở một trang cố định, không chuyển qua trang khác
Browser.drive {

        to SignupPage

        }
    `via()`: nên sử dụng khi việc test yêu cầu phải di chuyển giữa nhiều trang khác nhau
Browser.drive {

        via SignupPage

        }
  **Note:** Nếu không sử dụng Page Object thì có thể mở trực tiếp một page bằng cách sử dụng phương  thức `go()`

  Ví dụ:
go "http://google.com"
  hoặc
go “SignupPage”

4.2.3 Modules

  • Chỉ cần khai báo một lần.

  • Có thể được sử dụng nhiều lần, ở nhiều trang khác nhau hoặc lặp lại nội dung trên cùng một trang

  • Cấu trúc:

class ExampleModule extends Module {

       static content = {

       button { $("input", type: "submit") }

       }

     }
  • Hoặc có thế viết như sau:
class ExamplePage extends Page {

       static content = {

       theModule { module ExampleModule }

       }

     }
  • Cách dùng:
theModule.button.click()

4.2.4 Thao tác với content

Dùng $() để lấy ra các thành phần DOM của trang HTML.

Các cách sử dụng cơ bản:

  • Sử dụng CSS3 Selectors:
 $(«css selector», «index or range», «attribute/text matchers»)

     $("div.some-class p:first[title='something']")
  • Tìm kiếm theo chỉ số/name/class:
 $("h1", 2, class: "heading")

     $("p", name: "description")

     $("ul.someClass li", 2)
  • Tìm kiếm theo Text value:
$("h1", text: "All about Geb")
  • Find/Filter:
$("div").find(".b")

     $("div").filter(".c").parents()
 ...
  • Click: chỉ có tác dụng với thành phần đầu tiên tìm được.
$("input.loginButton").click(LoginPage)
  • Kiểm tra vị trí và kích thước của đối tượng đầu tiên tìm được (tính theo pixel và tính từ top left của page hoặc parent frame tới top left của đối tượng cần kiểm tra):
$("div").height == 20

     $("div").width == 40

     $("div").x == 60

     $("div").y == 80
  • Access tag name, attributes, text và classes:
<p title="a" class="a para">a</p>
 Access vào các thành phần của thẻ:
$("p").text() == "a"

     $("p").tag() == "p"

     $("p")[email protected] == "a"

     $("p").classes() == ["a", "para“]
  • Sending keystrokes: giả lập nhấn key hoặc tổ hợp keys trên bàn phím.

  • Setting giá trị cho thành phần tìm được:

    Dạng input box

    Dạng select box

    Dạng multiple select

    Dạng check box

    Dạng radio

    Upload file

  • Complex Interactions:

    Sử dụng trực tiếp WebDriver API (WebElement)

    Sử dụng Actions kế thừa từ WebDriver

    Sử dụng Interact Closures:

keyDown(Keys.SHIFT)
      doubleClick($('li.clicky'))
      keyUp(Keys.SHIFT)

4.2.5 Implicit Assertions

GEB cung cấp các phương thức kiểm tra để thao tác với các thành phần của page:

  • assert

  • at verification

  • wait/waitFor

assert:

  * Kiểm tra xem có thỏa mãn điều kiện đặt ra không.

  * Trả về giá trị True/False

Ví dụ:

assert 1 == 1
    assert $("h1")
    assert title == "Implicit Assertions!"

at verification:

  * Kiểm tra xem current page có phải là trang được chỉ định hay không.

Ví dụ:

class LoginPage extends Page {
       static url = "/login"
       static  content = {
       loginButton(to: AdminPage) { $("input", type: "submit", name: "login") }
       }
      }
       class AdminPage extends Page {
       static  at = {
       assert $("h1").text() == "Admin Page"
       }
      }
       Browser.drive {
       to LoginPage
       loginButton.click()
       at AdminPage
      }

waitFor:

  * Chờ một hoặc một cụm các biểu thức kiểm tra trả về giá trị True.

Ví dụ:

Browser.drive {
     waitFor { title == "Page Title" }
    }

4.2.6 Direct downloading

Trong Geb scripts sử dụng các phương thức download của Groovy để thực hiện download một file hoặc text từ một ứng dụng đã được chỉ định.

Ví dụ:

Browser.drive {
       go "http://myapp.com/login"

       // login
       username = "me"
       password = "secret"
       login().click()

       // now find the PDF download link
       def downloadLink = $("a.pdf-download-link")

       // now get the PDF bytes
       def bytes = downloadBytes([email protected])
      }

4.2.7 Reporting

  • Hỗ trợ việc lưu lại báo cáo kết quả của việc thực hiện test.

  • Bao gồm file log và ảnh chụp màn hình khi thực hiện test.

  • GEB cho phép config thư mục chứa report trong file pom.xmls

Ví dụ:

<systemPropertyVariables>
       <geb.build.reportsDir>target/test-reports/geb</geb.build.reportsDir>
     </systemPropertyVariables>

reportGroup: Hỗ trợ nhóm các report thành các thư mục con tiện cho việc quản lý report.

Ví dụ:

Browser.drive {
          reportGroup "google"
          go "http://google.com"
          report "home page"

          reportGroup "wikipedia"
          go "http://wikipedia.org"
          report "home page"
    }

reportingListener: Cho phép định nghĩa và thực hiện các thao tác khi report được tạo ra.

Ví dụ:

reportingListener = new ReportingListener() {
          void onReport(Reporter reporter, ReportState reportState, List<File> reportFiles) {
               reportFiles.each {
                    println "[[ATTACHMENT|$it.absolutePath]]"
               }
          }
     }

cleanReportGroupDir: Cho phép xóa một thư mục report cũ.

Ví dụ:

Browser.drive {
         cleanReportGroupDir()
         go "http://google.com"
         report "home page"
      }

5. Spock Framework

5.1 Giới thiệu về Spock Framework (Test Framework)

  • Spock là một framework kiểm tra và đặc tả cho ứng dụng Java và Groovy.

  • Là một ngôn ngữ đặc tả có tính diễn tả cao nên Spock nổi trội hơn so với các ngôn ngữ đặc tả khác.

  • Do Spock chạy JUnit nên nó tương thích với hầu hết các IDE như eclipse và IntelliJ

  • Link tham khảo về Spock: http://spockframework.github.io/spock/docs/1.0/spock_primer.html

  • Spock có một vài phương thức setup() và cleanup() truyền thống như sau:

    • def setup() – chạy trước tất cả các phương thức

    • def cleanup() – chạy sau tất cả các phương thức

    • def setupSpec() – chạy trước phương thức đầu tiên

    • def cleanupSpec() – chạy sau phương thức cuối cùng

Imports:
import spock.lang.*
   Package spock.lang bao gồm những kiểu quan trọng nhất cho việc viết đặc tả

5.2 Blocks trong Spock Framework

  • Blocks được coi là trái tim của Spock

  • Link tham thảo: http://spockframework.github.io/spock/docs/1.0/spock_primer.html

  • Các loại block chính:

    • given – Là cái được đưa ra để thực hiện test.

    • when – Là nhân tố kích thích.

    • then – Là trả về được mong đợi.

    • expect – Đưa ra kết quả mong muốn; Hữu dụng trong trường hợp nhân tố kích thích và kết quả mong đợi trong một biểu thức duy nhất.

      Ví dụ:

      Với when then:

when:
             def x = Math.max(1, 2)
             then:
             x == 2
     Với expect:
expect:
             Math.max(1, 2) == 2
 * and - Để phân chia các block khác nhau.

 * where - Luôn đứng cuối trong một phương thức và không thể được lặp lại; Được sử dụng để viết phương thức điều khiển bằng dữ liệu.

     Ví dụ:
def "computing the maximum of two numbers"() {
            expect:
            Math.max(a, b) == c

            where:
            a << [5, 3]
            b << [1, 9]
            c << [5, 9]
           }
      Ví dụ tổng thể
import geb.spock.GebSpec
             class GoogleWikipediaSpec extends GebSpec {

               def "first result for wikipedia search should be wikipedia"() {
                   given:
                 to GoogleHomePage
                   expect:
                 at GoogleHomePage
                   when:
                 search.field.value("wikipedia")
                   then:
                 waitFor { at GoogleResultsPage }
                   and:
                 firstResultLink.text() == "Wikipedia"
                   when:
                 firstResultLink.click()
                   then:
                 waitFor { at WikipediaPage }
               }
              }

5.3 Phương thức cố định (Fixture methods) trong Spock Framework

  • Spock có một vài phương thức setup() và cleanup() truyền thống như sau:

    • def setup() – chạy trước tất cả các phương thức

    • def cleanup() – chạy sau tất cả các phương thức

    • def setupSpec() – chạy trước phương thức đầu tiên

    • def cleanupSpec() – chạy sau phương thức cuối cùng

  • So sánh giữa Spock và JUnit

    • Mặc dù Spock sử dụng thuật ngữ khác nhưng có nhiều khái niệm và tính năng lấy cảm hứng từ JUnit. Sau đây là một số so sánh giữa Spock và JUnit:

10.jpg

   * JUnit chạy được test suite, Spock thì không hỗ trợ chạy suite

   * Với Spock ta có thể cấu hình chạy những file spec nếu nó được extend từ GebSpec hay GebReportingSpec

6. Jenkins

6.1 Sơ lược về Jenkins

  • Là một công cụ tích hợp liên tục mã nguồn mở, viết bằng java.

  • Cung cấp các dịch vụ tích hợp liên tục cho phát triển phần mềm:

    • Xây dựng và kiểm thử các project một cách liên tục.

    • Tự động quản lý việc chạy các job.

=> Jenkins là một quản gia cần mẫn cho project của bạn.

6.2 Cài đặt Jenkins

  • Windows: Cài đặt bằng windows installer

  • Ubuntu: Cài đặt bằng command trên Terminal

       wget -q -O - https://jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -
       sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list'
       sudo apt-get update
       sudo apt-get install jenkins
    

6.3 Cấu hình Jenkins

  • Địa chỉ: http://localhost:8080

  • Vào Manage Jenkins > Configure System

  • Cấu hình JDK:

    4.jpeg

  • Cấu hình Maven:

    5.jpeg

6.4 Tạo job trên Jenkins

  • Tạo Maven Job:

    • Chọn New Item

    • Đặt tên và chọn Maven project

    6.jpeg

    • Trong phần Configure, cấu hình file pom.xmlvà đặt câu lệnh test trong Goal and Options

7.jpeg

  • Lưu cấu hình

6.5 Cấu hình Git cho Jenkins

  • Chọn Manage Jenkins > Configure System

  • Cấu hình Git:

![8.jpeg](/uploads/17f9ddf1-9a4f-450f-9449-a811ce62eb03.jpeg)
  • Cấu hình Git trong Job: Tên Job > Configure
![9.jpeg](/uploads/70c4696c-81fe-490b-b07f-d731da0c5b87.jpeg)

6.6 Đặt lịch trên Jenkins

  • Chạy trực tiếp: Chọn Tên Job > Build Now

  • Đặt lịch chạy cho Job:

    • Chọn Tên Job > Configure > Build Trigger > Build periodically

    • Điền vào schedule theo mẫu: MINUTE HOUR DOM MONTH DOW

    Trong đó:

    MINUTE – số phút trong một giờ (0 – 59)

    HOUR – số giờ trong một ngày (0 – 23)

    DOM – số ngày của một tháng (1 – 31)

    MONTH – số tháng(0 – 11)

    DOW – số ngày của tuần (0 – 7) với 0 và 7 là chủ nhật

7. Demo

  • Tôi xin giới thiệu qua ba file code chính để viết nên một script bởi Geb:

    • LoginSpec.groovy – file này chứa các script test

    screenshot_2015_7_14.png

    • LoginPage.groovy – file này get các element

    login page - get cac element.jpg

    • TestSuite.groovy – file này sắp xếp các case

    screenshot_2015_7_14 (1).png

Và sau đây là phần demo chương trình

  • ####Các case test:

    • Đăng nhập:

      Để trống username và password.

      Username không hợp lệ và password hợp lệ.

      Username không đúng định dạng, password đúng.

      Username và password hợp lệ.

    • Đăng ký:

      Để trống tất cả các trường.

      Username hợp lệ và password trống.

      Tên để trống.

      Email đã đăng ký.

      Tất cả các trường hợp lệ.

    • Khác:

      Chọn giá trị từ drop-down list.

      Chọn giá trị checkbox.

{@youtube: https://www.youtube.com/watch?v=vp4FXbjTmTM&feature=youtu.be}

{@youtube: https://www.youtube.com/watch?v=DwXa9lUimDI&feature=youtu.be}

8. Kết luận

  • Với Geb, việc viết kịch bản thật rõ ràng mang lại hiệu quả mạnh mẽ và dễ bảo trì việc test các chức năng.

  • Nếu bạn chưa dùng Geb thì đây chính là cơ hội để khám phá tất cả mọi thứ mà Geb cung cấp, bởi đây là một công cụ mà ứng dụng web của bạn xứng đáng có được.

  • Hệ thống "the Geb mailing list" vô cùng linh động, hồi đáp kịp thời và thân thiện hỗ trợ trong quá trình sử dụng.

Tài liệu tham khảo

The Book Of Geb: Tài liệu tham khảo đầy đủ nhất về Geb