3.2. Cách sử dụng Behat
3.2.3. Xây dựng các định nghĩa bước
BDD hoạt đô ̣ng tương tự TDD, trước khi cài đă ̣t mã nguồn cho mỗi tính năng, cần phải viết kiểm thƣ̉ cho các tính năng đó. Behat hỗ trợ viê ̣c tƣ̣ đô ̣ng sinh các kiểm thử theo tương ứng một – một từ các định nghĩa bước trong tài liê ̣u mô tả của kịch bản thành các phương thức kiểm thử viết bằng mã nguồn PHP.
Behat cung cấp mô ̣t cơ chế để liên kết mô ̣t bước trong kịch bản và mô ̣t đi ̣nh nghĩa bước, nhờ cơ chế liên kết này Behat biết cần áp dụng phương thức kiểm thử nào tương ứng với mô ̣t tiêu chí kiểm thử chấp nhâ ̣n hê ̣ thống. Mỗi đi ̣nh nghĩa bước trong lớp FeatureContext bao gồm hai phần:
Phần đầu Behat sƣ̉ dụng chú thích khối của PHP để đƣa ra mô ̣t biểu thƣ́c chính quy tương ứng với bước đã được mô tả.
Phần thứ hai, Behat sử dụng mã nguồn PHP để viết mô ̣t phương thức kiểm thử tương ứng.
Chẳng hạn với bước được mô tả như sau:
When I do something with “value”
Sẽ có phương thức kiểm thử tương ứng trong lớp FeatureContext là:
/**
*/
publicfunctionsomeMethod($Arg) {
//code }
Phần mã nguồn nằm trong khối chú thích của PHP chính là biểu thƣ́c chính quy mà Behat sử du ̣ng để liên kết với mô tả bước. Phần này bao gồm:
Một từ khoá định nghĩa tương ứng với loại bước trong Gherkin, có ba loại từ khóa tương ứng ba loa ̣i bước là @When, @Then, @Given.
Sau tƣ̀ khóa, phần (/^I do something with "([^"]*)"$/) là biểu thức chính quy tương ứng với mô tả của ngữ cảnh theo ngôn ngữ Gherkin.
Mỗi phần"([^"]*)"$/) tương ứng với giá trị kiểm thử đã mô tả ở Gherkin sẽ tương ứng với một tham sốcủa phương thức kiểm thử.
Đối với một ứng dụng, để viết hết các định nghĩa bước tương ứng với các ngữ cảnh là việc không hề đơn giãn bởi vì có rất nhiều ngữ cảnh cho các tính năng của hệ thống. Tuy nhiên trong quá trình thực hiện, Behat sẽ hỗ trợ sinh ra các định nghĩa bước tương ứng, người lập trình chỉ cần bổ sung thêm các mã nguồn để kiểm thử thành công.
Quá trình thực hiện , Behatđo ̣c các bước của một kịch bản được viết bằng ngôn ngữ Gherkin ở tập tin .feature, nó sẽ so khớp với biểu thức chính quy đƣợc định nghĩa trong các lớp ngữ cảnh chứa trong FeatureContext.php để tìm phương thức kiểm thử tương ứng với bước đó .Tùy thuộc vào ngoại lệ trả về của phương thức kiểm thử và mối quan hê ̣ trước s au với các mô tả bước trong cùng kịch bản, Behat sẽ trả về một trong bảy loại kết quả thực thi khác nhau:
Bước thành công
Khi Behat tìm được định nghĩa bước tương ứng với mô tả bước, Behat sẽ thực thi chúng . Trong trường hợp phương thức định nghĩa không đưa ra một ngoại lệ, bước đó sẽ được đánh dấu là thành công (success). Các kết quả trả về
của phương thức định nghĩa ở lệnh return không có ý nghĩa đối với trạng thái thành công hay thất bại của chính định nghĩa đó.
Vd ex.feature
Feature: sample
Scenario: sample define
Given some step with "string" argument And number step with 12
FeatureContext.php
# features/bootstrap/FeatureContext.php
<?php
use Behat\Behat\Context\BehatContext;
class FeatureContext extends BehatContext {
/** @Given /^some step with "([^"]*)" argument$/ */
public function someStepWithArgument($argument1) {
}
/** @Given /^number step with (\d+)$/ */
public function numberStepWith($argument1) {
} }
Ở ví dụ này, quá trình thực hiện tập tin .feature, Behat tìm các định nghĩa lớp tương ứng trong FeatureContext, và việc thực hiện định nghĩa lớp đó. Mă ̣c dù phương thức định nghĩa không có mã nguồn cho kiểm thử , nhưng khi thực hiê ̣n phương thức này Behat không thấy tạo ra các ngoại lệ, do đó trường hợp này kiểm thử sẽ thành công. Trạng thái của bước thành công được đánh dấu màu xanh lá cây.
Bước chưa được định nghĩa
Khi Behat không tìm được định nghĩa lớp tương ứng với Step đang thực hiện thì bước đó sẽ được đánh dấu là bước chưa được đi ̣nh nghĩa (undefined).
Tất cả các bước đứng sau bước chưa đi ̣nh nghĩa của kịch bản đó sẽ bị bỏ qua.
Trạng thái của các bước chưa định nghĩa được đánh dấu màu vàng và Behat sẽ gợi ý một số định nghĩa lớp cho người dùng cài đặt.
Bước chưa được giải quyết
Khi phương thức định nghĩa của một bước trả ra một ngoại lệ thuộc Behat\Behat\Exception\PendingException, bước đó sẽ được đánh dấu là bước chƣa giải quyết (pending). Khi gặp một định nghĩa đang ở trạng thái pending, Behat muốn nhắc lâ ̣p trình viên nên viết các lệnh cho định nghĩa bước đó để đưa kiểm thử về tra ̣ng thái thành công . Tất cả các bước sau bước pending của cùng mô ̣t ki ̣ch bản sẽ bi ̣ bỏ qua.
Bước thất ba ̣i
Khi một phương thức định nghĩa đưa ra một ngoại lệ chung (không thuộc PendingException) trong quá trình thực hiện, bước đó sẽ được đánh dấu là thất bại. Cũng giống như bước thành công, các kết quả lập trình viên trả ra ở phương
thức định nghĩa không có ý nghĩa quyết định đến trạng thái thành công hay thất bại của bước. Tất cả các bước sau bước thất ba ̣i của cùng mô ̣t ki ̣ch bản sẽ bi ̣ bỏ
qua.
Bước bị bỏ qua
Behat sẽ không bao giờ thực hiện các bước được đặt sau các bước có trạng thái chưa đi ̣nh nghĩa , bước chưa được giải quyết hoă ̣c bước thất ba ̣i . Các bước này gọi là các bước bị bỏ qua và trạng thái của chúng được đánh dấu là skipped.
Việc cài đặt phương thức định nghĩa lớp không có ý nghĩa trong trường hợp này.
Bước nhập nhằng
Nếu trong quá trình thực hiện Behat tìm thấy nhiều định nghĩa cho cùng một bước thì bước đó sẽ định đánh dấu trạng thái là bước nhập nhằng. Chẳng hạn:
<?php
use Behat\Behat\Context\BehatContext;
class FeatureContext extends BehatContext {
/** @Given /^.* step with .*$/ */
public function someStepWithArgument() {
}
/** @Given /^number step with (\d+)$/ */
public function numberStepWith($argument1) {
} }
Khi bắt gặp các bước nhập nhằng, Behat đưa ra các thông báo gợi ý cho người lập trình định nghĩa phương thức lớp, Behat không tự lựa chọn định nghĩa bước phù hợp cho bước đó.
Các định nghĩa bước dư thừa
Behat chỉ cho phép mỗi biểu thức chính quy tương ứng với một định nghĩa bước được viết một lần duy nhất. Khi khai báo trong FeatureContext, nếu người lập trình sử dụng các biểu thức chính quy giống nhau Behat sẽ thông báo lỗi dƣ thừa định nghĩa bước.Ví dụ:
<?php
use Behat\Behat\Context\BehatContext;
class FeatureContext extends BehatContext {
/** @Given /^number step with (\d+)$/ */
public function workWithNumber($number1)
{ }
/** @Given /^number step with (\d+)$/ */
public function workDifferentlyWithNumber($number1) {
} }
Ở ví dụ này, khi đọc FeatureContext, Behat tìm thấy biểu thức /** @Given /^number step with (\d+)$/ */ được định nghĩa hai lần, mặc dù hai phương thức có tên khác nhau nhƣng Behat vẫn sẽ báo lỗi, bởi quá trình so sánh chỉ diễn ra ở phầnmô tả bước và biểu thức chính quy viết trên mỗi phương thức định nghĩa bước.
Biến đổi tham số bước
Biến đổi tham số bước cho phép người lập trình trừu tượng việc thực hiện các thao tác thông thường trên các tham số định nghĩa bước vào các phương thức có thể tái sử dụng. Hơn nữa, các phương thức này cũng có thể được sử dụng để chuyển từ một tham số xâu thông thường được dùng như tham số cho phương thức định nghĩa bước thành một loại dữ liệu hoặc đối tượng cụ thể.
Mỗi phương thức chuyển đổi phải trả ra một giá trị mới, giá trị này thay thế cho giá trị chuỗi ban đầu và nó được sử dụng như một tham số cho phương thức định nghĩa bước.Phương thức chuyển đổi được định nghĩa bằng cách sử dụng kiểu chú thích giống như các phương thức định nghĩa bước kèm với từ khoá
@Transform, theo sau đó là biểu thức chính quy của bước đó.
Ví dụ: Tự động chuyển một tham số kiểu số sang một tham số số nguyên.
<?php
use Behat\Behat\Context\BehatContext;
class FeatureContext extends BehatContext {
/**
* @Transform /^(\d+)$/
*/
public function castStringToNumber($string) {
return intval($string);
} /**
* @Then /^a user '([^']+)', should have (\d+) followers$/
*/
public function assertUserHasFollowers($name, $count)
if ('integer' !== gettype($count)) { throw new Exception('Integer expected');
} } }