1. Giới thiệu về cloud browser testing

  • Để thực hiện kiểm thử một website trên nhiều trình duyệt và nền tảng hệ điều hành khác nhau, cần mất rất nhiều thời gian cấu hình và thực hiện kiểm thử trên từng trình duyệt và nền tảng hệ điều hành, kể cả khi sử dụng kiểm thử tự động. Thêm nữa, khi sử dụng các driver trình duyệt của một công cụ như Selenium cũng có những điểm khác biệt với một trình duyệt thật sự. Do đó, đã có một vài dịch vụ "remote web browsers" được cung cấp để thực hiện các thao tác kiểm thử đa môi trường từ xa mà không cần tốn công sức và tiền bạc cho việc chuẩn bị máy móc và môi trường kiểm thử. Với những người đã sử dụng các công cụ kiểm thử tự động như Selenium hoặc GEB framework, có hai dịch vụ khá tốt đó là SauceLabsBrowserStack. Chúng cung cấp các trình duyệt thực sự chạy trên các nên tảng hệ điều hành khác nhau, giúp cho việc kiểm thử trên môi trường thật dễ dàng hơn bao giờ hết.
  • Trong bài nghiên cứu này, chúng ta sẽ cùng tìm hiểu cách tích hợp SauceLabs và BrowserStack cho Geb framework trong một project Gradle.

2. Tạo driver test cho SauceLabs và BrowserStack

  • Khi tạo tài khoản trên SauceLabsBrowserStack, chúng ta sẽ có các thông tin về tài khoản như sau: Screenshot from 2015-07-27 14:58:14.png Screenshot from 2015-07-27 15:04:30.png

  • Cả SauceLabs và BrowserStack đều là dịch vụ trả phí, với SauceLabs bản dùng thử cho phép bạn sử dụng trong 30 ngày. Với BrowserStack bản dùng thử cung cấp 30 phút thực hiện kiểm thử truyền thống và 100 phút kiểm thử tự động.

  • Cả SauceLabs và BrowserStack đều cung cấp một driver để đưa ra thông tin về trình duyệt cũng như tài khoản và access key, tạo một đối tượng của RemoteWebDriver để cấu hình trình duyệt sử dụng trên đám mây. Khi Geb nhận được các cấu hình phù hợp để chạy trên SauceLabs/BrowserStack, nó sẽ gọi lên đám mây, còn không Geb sẽ sử dụng các cấu hình(nếu có) đã được thiết lập để chạy trên máy cục bộ. Dưới đây là ví dụ về tham số của trình duyệt khi cấu hình chạy trên SauceLabs/BrowserStack(sẽ truyền lên phương thức create() trên đám mây):

browserName_platform_version {
     capabilities(
         browserName : «"tên trình duyệt được liệt kê trong org.openqa.selenium.remote.BrowserType"»
         platform : «"tên nền tảng được liệt kê trong org.openqa.selenium.Platform"»
         version : «"phiên bản"»
     )
}

- Giả sử bạn đang sử dụng cấu hình như bên dưới để chạy lệnh thông qua SauceLabs với Firefox 19 trên Linux, bạn sẽ chỉ ra các thuộc tính của `geb.saucelabs.browser` như sau:
```Groovy

firefox_linux_19 {
		capabilities(
			browserName: "fireFox",
			platform: "LINUX",
			version: "19"
			)
		}

và chạy với IE 9 trên Vista như sau:


internet_explorer_vista_9 {
            capabilities(
                    browserName: "internet explorer",
                    platform: "VISTA",
                    version: "9"
            )
        }

  • Một số trình duyệt như Chrome tự đông update lên phiên bản mới nhất, nên bạn không cần chỉ định version, như dưới đây:

chrome_mac {
		capabilities(
			browserName: "chrome",
			platform: "MAC"
			)
		}

- Có một cách khác để truyền tham số lên dịch vụ của SauceLabs/BrowserStack đó là sử dụng hàm `capability()`. Sử dụng hàm này sẽ hữu dụng trong trường hợp cần truyền một số tham số đặc biệt. Ví dụ khi muốn hiển thị Visual Logs của một task trên BrowserStack chúng ta cần truyền tham số `browserstack.debug` là `true`. Nếu truyền tham số này bằng hàm `capabilities()` như trên thì khi build project sẽ gặp lỗi về cú pháp mặc dù tham số đúng. Trong trường hợp này chúng ta buộc phải sử dụng hàm `capability()` để truyền tham số như bên dưới:

```Groovy
chrome_window_7{
        capabilities(
            name: "Windows 7 Chrome",
            browser: "Chrome",
            os: "WINDOWS",
            os_version: "7",
            version: "43",
            passed: "true"
            )
            capability("browserstack.debug","true")
        }

- Trong trường hợp không viết các thuộc tính trong hàm `capabilities()` cũng như `capability()`, SauceLabs/BrowserStack sẽ sử dụng các tùy chọn mặc định. Việc đặt tên các task theo tên trình duyệt, hệ điều hành và phiên bản của trình duyệt sẽ tốt cho việc tìm kiếm và phân biệt các task với nhau.
- Dưới đây là danh sách đầy đủ các trình duyệt, phiên bản và hệ điều hành mà SauceLabs và BrowserStack hỗ trợ:
 - [Danh sách nền tảng được SauceLabs hỗ trợ](https://saucelabs.com/platforms/)
 - [Danh sách trình duyệt và nền tảng của BrowserStack](https://www.browserstack.com/list-of-browsers-and-platforms?product=live)
- SauceLabs và BrowserStack cũng cho phép truyền thêm một số cấu hình tùy chọn bằng cách cung cấp một danh sách các tham số truyền lên(thông qua phương thức `create()`) như dưới đây:
 - [Danh sách tùy chọn cấu hình của SauceLabs](https://saucelabs.com/docs/additional-config)
 - [Danh sách cấu hình của BrowserStack](http://www.browserstack.com/automate/capabilities)

##3. `SauceLabsDriverFacetory` và `BrowserStackDriverFactory`

- Dưới đây là ví dụ cách sử dụng của `SauceLabsDriverFactory` và `BrowserStackDriverFactory` trong file GebConfig.groovy để cấu hình driver sử dụng trình duyệt trên đám mây của SauceLabs/BrowserStack:
 - SauceLabs:
```Groovy

def sauceLabsBrowser = System.getProperty("geb.saucelabs.browser")
	if (sauceLabsBrowser) {
		driver = {
			def username = System.getenv("GEB_SAUCE_LABS_USER")
			assert username
			def accessKey = System.getenv("GEB_SAUCE_LABS_ACCESS_PASSWORD")
			assert accessKey
			new SauceLabsDriverFactory().create(sauceLabsBrowser, username, accessKey)
		}
}

  • BrowserStack:

def browserStackBrowser = System.getProperty("geb.browserstack.browser")
	if (browserStackBrowser) {
		driver = {
			def username = System.getenv("GEB_BROWSERSTACK_USERNAME")
			assert username
			def accessKey = System.getenv("GEB_BROWSERSTACK_AUTHKEY")
			assert accessKey
			new BrowserStackDriverFactory().create(browserStackBrowser, username, accessKey)
		}
}

  • Nếu muốn kiểm thử server cục bộ bằng cách sử dụng localIdentifier:

def browserStackBrowser = System.getProperty("geb.browserstack.browser")
if (browserStackBrowser) {
            driver = {
            	def username = System.getenv("GEB_BROWSERSTACK_USERNAME")
            	assert username
            	def accessKey = System.getenv("GEB_BROWSERSTACK_AUTHKEY")
            	assert accessKey
            	def localId = System.getenv("GEB_BROWSERSTACK_LOCALID")
            	assert localId
            	new BrowserStackDriverFactory().create(browserStackBrowser, username, accessKey, localId)
            }
}

## 4. Gradle plugins

- Geb cung cấp Gradle plugin cho cả SauceLabs và BrowserStack, với cách khai báo tài khoản và trình duyệt đơn giản, cũng như cầu hình kết nối cho phép các dịch vụ đám mây truy câp tới các ứng dụng cục bộ. Các plugin này cho phép tạo nhiều task kiểm thử một cách dễ dàng và phù hợp với thuộc tính `geb.PROVIDER.browser` đã được thiết lập (với `PROVIDER` là `saucelabs` hoặc `browserstack`). Giá trị của thuộc tính có thể được truyền trong file cấu hình tới `SauceLabsDriverFactory`/`BrowserStackDriverFactory` ở trên mục 3 được gọi là ”browser specification“ (đặc tả của trình duyệt). Dưới đây là ví dụ cho SauceLabs và BrowserStack.

### 4.1 geb-saucelabs plugin

Dưới đây là ví dụ sử dụng geb-saucelabs Gradle plugin.

```Groovy
apply plugin: "geb-saucelabs"		(1)
buildscript {		(2)
		repositories {
			mavenCentral()
		}
		dependencies {
			classpath 'org.gebish:geb-gradle:0.12.0'
		}
}
repositories {		(3)
		maven { url "http://repository-saucelabs.forge.cloudbees.com/release" }
}
dependencies {		(4)
		sauceConnect "com.saucelabs:ci-sauce:1.81"
}
sauceLabs {
	browsers {
		chrome_mac		(5)
		safari_mac_8
		firefox_linux_39 {		(6)
			capabilities(
				name: "FireFox Linux 39 Test",
				browserName: "FireFox",
				version: "39"
				passed: "true"
			)
		}
	}
	task {		(7)
		testClassesDir = test.testClassesDir
		testSrcDirs = test.testSrcDirs
		classpath = test.classpath
	}
	account {		(8)
		username = "vannhuy"
		accessKey = "38ca7807-5e08-4a25-8592-xxxxxxxxxxxx"
	}
	connect {		(9)
		port = 4444		(10)
		additionalOptions = ['--proxy', 'proxy.example.com:8080']		(11)
	}
}

(1) Gắn plugin vào project.
(2) Chỉ định làm cách nào để phân tích và download plugin.
(3) Khai báo địa chỉ để download SauceConnect.
(4) Khai báo phiên bản của SauceConnect được sử dụng như một phần của cấu hình sauceConnect. Sử dụng để tạo kết nối SauceConnect tới SauceLabs trước khi chạy một task. Điều này nghĩa là các trình duyệt trên đám mây sẽ có một "localhost pointing" ở máy cục bộ.
(5) Khai báo hai task kiểm thử trên các trình duyệt sử dụng cú pháp khai báo rút gọn, chúng sẽ tạo ra các Test task như sau: chromeMacTest, safariMac8Test. Với cú pháp khai báo rút gọn, tất cả tên của task trên lịch sử của SauceLabs đều là unnamed job và kết quả là Finished.
(6) Khai báo chỉ định rõ ràng các tham số truyền lên, nó sẽ tạo ra một Test task như sau: firefoxLinux39Test.
(7) Cấu hinh tất cả các task kiểm thử được tạo ra; mỗi task kiểm thử sẽ được gắn và chạy với một Test task cố định.
(8) Truyền thông tin nhận dạng cho SauceConnect.
(9) Cấu hình tùy chọn của SauceConnect.
(10) Ghi đè cổng được sử dụng bởi SauceConnect, mặc định là 4445.
(11) Truyền thêm lệnh tùy chọn (cho proxy nếu có) tới SauceConnect.

  • Lưu ý: Có thể sử dụng allSauceLabsTests task để chạy tất cả các task kiểm thử có trong build sử dụng dịch vụ SauceLabs.
  • Đây là trang lịch sử kiểm thử tự động của SauceLabs SauceLabsHistory1.png SauceLabsHistory2.png

4.2 geb-browserstack plugin

Dưới đây là ví dụ sử dụng geb-browserstack Gradle plugin.

apply plugin: "geb-browserstack"		(1)
buildscript {
	repositories {		(2)
		mavenCentral()
	}
	dependencies {
		classpath 'org.gebish:geb-gradle:0.12.0'
	}
}
browserStack {
	application 'http://ngocthoainguyen.herokuapp.com/signin'		(3)
	forceLocal = true		(4)
	browsers {		(5)
		chrome_mac
		chrome_windows_7{		(6)
			capabilities(
				name: "Windows 7 Chrome",
				browser: "Chrome",
				os: "WINDOWS",
				os_version: "7",
				version: "43",
				passed: "true"
			)
			capability("browserstack.debug","true")
		}
	}
	task {		(7)
        testClassesDir = test.testClassesDir
        testSrcDirs = test.testSrcDirs
        classpath = test.classpath
    }
    account {		(8)
        username = "nguyenthanhdat1"
        accessKey = "kRtnFDmSGPRExxxxxxxx"
    }
}

(1) Gắn plugin vào project.
(2) Chỉ định làm cách nào để phân tích và download plugin.
(3) Chỉ định các URL mà "BrowserStack Tunnel" có thể truy cập. Có thể chỉ định được nhiều application. Nếu không có application nào được chỉ định, kết nối sẽ không bị giới hạn tới các URL cụ thể.
(4) Cấu hình kết nối của BrowserStack để gửi tất cả thông tin thông qua máy cục bộ. Thuộc tính cấu hình quản lý điều này là forcelocal và giá trị mặc định là false.
(5) Khai báo một task kiểm thử trên trình duyệt chrome sử dụng cú pháp khai báo rút gọn, nó sẽ tạo ra một Test task như sau: chromeMacTest. Với cú pháp khai báo rút gọn, tất cả tên của task trên lịch sử của BrowserStack đều được tự động tạo ra.
(6) Khai báo chỉ định rõ ràng các tham số truyền lên, nó sẽ tạo ra một Test task như sau: chromeWindows7Test.
(7) Cấu hinh tất cả các task kiểm thử được tạo ra; mỗi task kiểm thử sẽ được gắn và chạy với một Test task cố định.
(8) Truyền thông tin nhận dạng cho BrowserStack.

  • Lưu ý: Có thể sử dụng allBrowserStackTests task để chạy tất cả các task kiểm thử có trong build sử dụng dịch vụ BrowserStack.
  • Đây là trang lịch sử kiểm thử tự động của BrowserStack BrowserStackHistory1.png BrowserStackHistory2.png

5. Ví dụ tham khảo

Thông tin tham khảo khác