Xu hướng ngày càng phổ biến của các chuẩn mới về sản xuất phần mềm là yêu cầu các developers viết unit test khi cài đặt source code. Việc viết unit trước đó rất hạn chế, ít, nhiều khi còn không được thực hiện trong các dự án.

Bài viết xin giới thiệu một trong những công cụ phổ biến và hữu dụng được sử dụng để viết Unit test có một cái tên rất đặc biệt “cucumber – dưa chuột”.

Nội dung bài viết :

1. Cucumber là gì.

2. Ngôn ngữ Gherkin.

3. Hướng dẫn cài đặt Cucumber.

4. Tổng kết.

Đầu tiên Cucumber là gì.

Cucumber là một công cụ kiểm thử tự động dựa trên việc thực thi các functions được mô tả dướng dạng plain-text, để support cho việc viết Behavior Driven Development( trong bày viết mình viết tắt là BDD) của các developers.
Các kịch bản được gọi là scenarios sẽ được viết trước và thể hiện nghiệp vụ, sau đó source code mới được cài đặt để pass qua tất cả các stories đó.
Ngôn ngữ được cucumber sử dụng là “Gherkin”. Bản chất Cucumber được viết bằng Ruby nhưng chúng ta có thể sử dụng để test code được viết bằng Ruby, PHP, Java, C# và Python.

Ngôn ngữ Gherkin

Gherkin dịch sang tiếng Việt là “giống dưa chuột”. Gherkin là ngôn ngữ mà Cucumber có thể hiểu được. Hiểu đơn giản vậy thôi nhé :smile: .
Gherkin là một ngôn ngữ thể hiện nghiệp vụ và có miền ngữ nghĩa xác định giúp cho người đọc có thể hiểu được kịch bản và hành động mà không cần biết chi tiết chúng được cài đặt như thế nào.

Quy tắc khi viết Gherkin
  • Source file gherkin là .feature.

  • Một file chỉ mô tả một feature.

  • Cú pháp của gherkin

Đặc điểm

– Giống như PythonYAML, Gherkin là một ngôn ngữ kịch bản được sử dụng để định nghĩa logic theo cấu trúc. Hay giống như Ruby, nên thay thế kí tự tab bằng các kí tự space, dòng comment sẽ có kí tự # ở đầu dòng.

– Bắt đầu một file sẽ là Feature, sau đó là scenarios và steps.
Khi chúng ta chạy file source “.feature” mỗi step sẽ match với một code block được định nghĩa sẵn trước đó gọi là “Step Definitions”.

BDD trong Cucumber

Cú pháp BDD trong cucumber là : Given, When , Then. Ngoài ra một số trường hợp phức tạp hơn có thêm And, But ...

Given : Sử dụng để mô tả bối cảnh ban đầu. Đưa vào hệ thống một trạng thái bắt đầu tương tác với hệ thống.

When : Mô tả các sự kiện hành động chính mà người dùng thực hiện.

Then : Mục đích quan sát kết quả liên quan trong feature.

Ví dụ về một đoạn code Gherkin kiểm tra chức năng login:

Feature: Test login

Scenario Outline: Login Success and Failure
	Given I navigate to the mock application
	When I try to login with valid credentials
	Then I should see that I logged in successfully

Cách cài đặt

Đơn giản sử dụng nmp để thực hiện cài đặt như sau :

npm install cucumber

Thử sử dụng cucumber trong node js

Ở bài viết này chúng ta sử dụng node để thực hiện viết Test. Nội dung kiểm tra xem đoạn text có tồn tại trên một page hay không.

Cài đặt thư viện :

$ npm install -S express multiline
$ npm install --save-dev cucumber@latest selenium-webdriver@3.0.1 chromedriver@2.25.1

Khi thực hiện hai câu lệnh trên chúng ta có nội dung file package.json như dưới.

package.json
{
  "name": "cucumnerjs-example",
  "version": "1.0.0",
  "description": "example",
  "main": "index.js",
  "scripts": {
    "test": "./node_modules/.bin/cucumber.js",
    "start": "node index.js"
  },
  "author": "jibun",
  "license": "MIT",
  "dependencies": {
    "express": "^4.14.0",
    "multiline": "^1.0.2"
  },
  "devDependencies": {
    "chromedriver": "^2.25.1",
    "cucumber": "^2.0.0-rc.6",
    "selenium-webdriver": "^3.0.1"
  }
}

Tạo app để sử dụng test

Trong thư mục src tạo file index js và file index.js như dưới.

src/index.js
const express = require('express')
const multiline = require('multiline')
const app = express()

app.get('/', (req, res) => {
    res.send(multiline( () => {/*
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <p>Cucumber-js example</p>
  </body>
</html>
  */}))
})

module.exports = app
index.js
const app = require('./src/index')

app.listen(3000, () => {
    console.log('port 3000')
})

Sử dụng câu lệnh npm start để thực hiện start app. Kết quả như sau.

$ npm start

> cucumnerjs-example@1.0.0 start /develop/node/cucumberjs
> node index.js

port 3000

Ok, Vậy chúng ta đã tạo app thành công. Tiếp theo chúng ta chuẩn bị test bằng cucumber js.

Tạo thư mục features sử dụng lệnh mkdir rồi thực hiện chạy test thử.

$ mkdir features
$ npm test

> cucumnerjs-example@1.0.0 test /develop/node/cucumberjs
> cucumber.js 

0 scenarios
0 steps
0m00.000s

Như kết quả ở trên thì chúng ta chưa có scenarios và steps nào cả. Bước tiếp theo sẽ thực hiện viết các scenarios bằng Gherkin.

features/example.feature
Feature: Example feature
  As a user of Cucumber.js
  I want to have example application
  So that I can concentrate on building awesome applications

  Scenario: I am on the TopPage
    Given I am on the TopPage
    Then I should see "Cucumber-js example"

Nội dung đoạn feature trên :

  • Given I am on the TopPage

  • Then I should see "Cucumber-js example"

Ok, chúng ta thực hiện chạy thử. Kết quả sẽ hiển thị như sau.

Feature: Example feature

    As a user of Cucumber.js
    I want to have documentation on Cucumber
    So that I can concentrate on building awesome applications

  Scenario: I am on the TopPage
  ? Given I am on the TopPage
  ? Then I should see "Cucumber-js example"

Warnings:

1) Scenario: I am on the TopPage - features/documentation.feature:6
   Step: Given I am on the TopPage - features/documentation.feature:7
   Message:
     Undefined. Implement with the following snippet:

       Given('I am on the TopPage', function (callback) {
         // Write code here that turns the phrase above into concrete actions
         callback(null, 'pending');
       });

2) Scenario: I am on the TopPage - features/documentation.feature:6
   Step: Then I should see "Cucumber-js example" - features/documentation.feature:8
   Message:
     Undefined. Implement with the following snippet:

       Then('I should see {arg1:stringInDoubleQuotes}', function (arg1, callback) {
         // Write code here that turns the phrase above into concrete actions
         callback(null, 'pending');
       });

1 scenario (1 undefined)
2 steps (2 undefined)
0m00.000s
npm ERR! Test failed.  See above for more details.

Nguyên nhân chúng ta nhận được lỗi là do chưa thực hiện viết các hành vi tương tác với feature.
Các thiết lập cơ bản để thự hiện test là thiết lập các driver, step, hook.

Thiết lập driver

Thiết lập web driver để thực hiện test trước.

features/support/world.js
require('chromedriver')
var seleniumWebdriver = require('selenium-webdriver');
var {defineSupportCode} = require('cucumber');

function CustomWorld() {
  this.driver = new seleniumWebdriver.Builder()
    .forBrowser('chrome')
    .build();
}

defineSupportCode(function({setWorldConstructor}) {
  setWorldConstructor(CustomWorld)
})
Viết miêu tả các step trong gherkin
features/step_definitions/browser_steps.js
var seleniumWebdriver = require('selenium-webdriver');
var {defineSupportCode} = require('cucumber');

defineSupportCode(function({Given, Then}) {
    Given('I am on the TopPage', function () {
      return this.driver.get('http://localhost:3000');
    });
    Then('I should see {stringInDoubleQuotes}', function (text) {
        const xpath = "//*[contains(text(),'" + text + "')]"
        const condition = seleniumWebdriver.until.elementLocated({xpath: xpath})

        return this.driver.wait(condition, 10000)
    });
});
Thiết lập hook

Đi tới file hooks.js, có thể viết code muốn thực hiện sau khi thực thi scenario.

var {defineSupportCode} = require('cucumber');

defineSupportCode(function({After}) {
  After(function() {
    return this.driver.quit();
  });
});

Vậy là đã thiết lập OK, Giờ chúng ta thực hiện chạy test thêm một lần nữa xem nào.

$ npm test

> cucumnerjs-example@1.0.0 test /develop/node/cucumberjs
> cucumber.js

Feature: Example feature

    As a user of Cucumber.js
    I want to have documentation on Cucumber
    So that I can concentrate on building awesome applications

  Scenario: I am on the TopPage
  ✔ Given I am on the TopPage
  ✔ Then I should see "Cucumber-js example"

1 scenario (1 passed)
2 steps (2 passed)
0m01.406s

**Kết quả **:

1 scenario (1 passed)  
2 steps (2 passed)

Tổng kết

Cucumber là một trong những gem rất là hữu dụng trong các Framework. Hơn nữa có Cucumber Js có thể kết hợp với rất nhiều các thư viện js khác để thực hiện BDD trở lên tốt hơn nữa. Ở các bài viết tiếp theo chúng ta sẽ đi vào các ví dụ cụ thể, cũng như cách kết hợp các thư viện js khác nhau để viết Auto Test.

Tham khảo