Cucumber (P3) - Parameters và Scenario Outline

phần 1 bạn viết các thành phần trong Cucumber như Features, Screnario, Step Definitions và phần 2 bạn đã cài đặt xong môi trường, bây giờ chúng ta sẽ bắt đầu viết script đầu tiên.

Demo Script

  1. Mở Project → chuột phải package nằm trong thư mục src/test/java → tạo file feature mới, vd: steps.feature

Create feature file

  1. Tạo 2 kịch bản để demo trên trang facebook như sau:
Feature: annotation 
#This is how background can be used to eliminate duplicate steps 

Scenario: Login failed
	Given User navigates to Facebook 
	When I enter username as firstUser
	And I enter password as password
	And I click Login button
	Then Login should fail 
	
	
Scenario: reLogin
	Given User navigates to Facebook 
	When I enter username as secondUser 
	And I enter password as password
	And I click Login button 
	Then Relogin option should be available
	Then Login should fail 

Save fileRun as Cucumber Feature, bạn sẽ thấy ở màn hình console thông báo 8 steps underfined, hiển nhiên là vậy vì Cucumber sẽ tìm code cài đặt step (còn gọi là step definition) để đối chiếu với hành vi mà bạn đã nghĩa trong file feature, mà ở đây bạn chưa cài đặt. Phần dưới bạn quan sát sẽ thấy vài đoạn code gợi ý về việc cài đặt steps, bạn sẽ cài đặt đoạn code này trong phần step definition.

Cucumber console

@Given("^User navigates to Facebook$")
@When("^I enter username as firstUser$")
@When("^I enter password as password$")
@Then("^Relogin option should be available$")
@Then("^Login should fail$")

Bạn chú ý rằng các chú thích (annotation) đóng vai trò không quá quan trọng trong Cucumer, ở ví dụ trên bạn có thể thay Given -> When, When -> And thì script của bạn vẫn chạy ngon lành, cái thực sự quan trọng là chuỗi chỉ dẫn bên trong annoation trong file feature và file step definition phải khớp nhau.

  1. Tạo file StepDefinition.java trong cùng package với file feature, sau đó bạn copy đoạn code gợi ý ở màn hình console vào class vừa tạo. Để có thể thao tác trên trình duyệt, mình sẽ dùng API của selenium frameword, ở đây, mình khai báo một đối trượng là WebDriver và khởi tạo nó đồng thời import thư viện org.openqa.selenium.WebDriver;

Dùng XPath Locator để định vị trường username và password, sau đó truyền giá trị thông qua đối số (parameters) userName và pass:

@When("^I enter username as firstUser$")
public void i_enter_username_as_firstUser() throws Throwable {
		driver.findElement(By.id("email")).sendKeys("firstUser");
    }
    
@When("^I enter password as password$")
public void i_enter_password_as_password() throws Throwable {
		driver.findElement(By.id("pass")).sendKeys("password");
	}

Sau khi cài đặt xong step definitions, bạn chọn file feature và Run as Cucumber feature, ở đây mình có 2 scenarios, Cucumber sẽ thực hiện 2 scenarios này một cách độc lập và cho kết quả như sau:

Ressult

Tuy nhiên kiểm tra kết quả dựa trên màn hình Console không phải là một ý tưởng hay, chúng ta sẽ chạy nó bằng JUnit hoặc TestNG bằng cách: thêm file runTest.java vào cùng package với file feature và stepDefinition, sau đó import thư viện cucumber.junit.Cucumber và chạy lại file Run as JUnit

import org.junit.runner.RunWith; 
import cucumber.junit.Cucumber; 

@RunWith(Cucumber.class) 
@Cucumber.Options(format = {"pretty", "html:target/cucumber"}) 

public class runTest {

Bạn có thể thấy kết quả sau khi chạy test rất rõ ràng và dễ hiểu.

Result - JUnit

bạn có thể tham khảo TestNG, JUnit tại bài viết trước của mình.

Parameters & Scenario Outline

Giả sử bộ data test của bạn bây giờ không chỉ gồm firstUser/password, secondUser/password mà nUser/password, bạn cần chạy hết bộ dữ liệu để đạt được độ bao phủ cao nhất cho feature login này, theo cách thông thường cứ ứng với mỗi bộ user thì bạn cần tạo cho nó một scenario tương ứng, như vậy bạn cần tới n scenario!, như vậy có vẻ không phải là một cách tốt, vì đoạn code và câu lệnh sẽ bị lặp lại rất nhiều, mà điều này cấm kị trong lập trình. Cucumber hỗ trợ sử dụng ParametersScenario Outline để bạn giải quyết các vấn đề như trên.

Mình sẽ giữ nguyên phần không đổi của các scenario, còn những data thay đổi thì đặt trong dấu ngoặc kép " ", mình sẽ demo trong 1 scenario như thế này nhé:

Feature: Login fail 

Scenario: Login failed
	Given User go to Facebook 
	When I enter username as "nUser"
	And I enter password as "password"
	And I click Login button
	Then Login should fail 

Sau khi compile, bạn sẽ thấy dòng code gợi ý lại xuất hiện:

@When("^I enter username as \"([^\"]*)\"$")
@When("^I enter password as \"([^\"]*)\"$")

Ở đây, "nUser" và "password" mà bạn đã định nghĩa trong file feature trên được hiểu là chuỗi xâu, khi chuyển đổi sang step definition, Cucumer dùng Regex pattern để mô tả nó, Regex sẽ được nói ở các phần sau. Tiếp theo, bạn sửa và cài đặt chi tiết đoạn code trên trong file StepDefinition.java như dưới đây, chú ý là thay vì đưa giá trị hardcode (vd: firstUser, password) thì chúng ta truyền tham số (vd: String userName) và sử dụng giá trị này như một biến trong hàm.

@When("^I enter username as \"([^\"]*)\"$")
	public void i_enter_username_as(String userName) throws Throwable {
		driver.findElement(By.id("email")).sendKeys(userName);
	}

@When("^I enter password as \"([^\"]*)\"$")
	public void i_enter_password_as(String password) throws Throwable {
		driver.findElement(By.id("pass")).sendKeys(password);
}

Bạn save và chạy lại file thành công, như vậy là ta đã thêm parameters cho scenario test demo. Tiếp theo, làm sao để chạy cùng một scenario với nhiều bộ data test khác nhau trong khi các steps vẫn giữ nguyên thì khi đó bạn dùng tới Scenario Outline. Bạn thay đổi tên khai báo Scenario → Scenario Outline, thêm bộ ngoặc <> vào parameters và cung cấp bộ data test sau từ khóa Examples

Feature: Login fail

Scenario Outline: Login failed
	Given User navigates to Facebook 
	When I enter username as "<nUser>"
	And I enter password as "<password>"
	And I click Login button
	Then Login should fail 
	Examples: Page titles 
	    | nUser      | password  |
		| firstUser  | password1 |
		| secondUser | password2 |
		| thirdUser  | password3 |
		| fourthUser | password4 |

Với mỗi bộ data test: nUser - password, Cucumber sẽ thực thi nó như là một scenario độc lập, kết quả của scenario sau không phụ thuộc vào kết quả của scenario trước. Đầu tiên Cucumber sẽ tìm các paramters ("<nUser>") và chèn data được cung cấp trong Examples (firstUser) để tạo ra một scenario hoàn chỉnh, sau đó nó tìm step definition tương ứng và chạy test thành công. Chọn file runTest.java và Run as JUnit, ta có kết quả sau:

Result all

Bạn có thể tùy chỉnh tham số và giá trị trong Examples cho phù hợp với mục đích test trong dự án, ở phần tiếp theo chúng ta sẽ tìm hiểu TagDatatables. Enjoy it!

Source code https://github.com/TrangVuUet/demoCucumber