本文目录导读:

我来详细讲解PHP中使用Behat进行行为驱动开发(BDD)测试的方法。
Behat简介
Behat是PHP的BDD测试框架,用于测试应用程序的业务行为,它允许你用人类可读的语言描述功能,然后自动验证。
安装Behat
使用Composer安装
# 创建项目目录 mkdir my-project cd my-project # 初始化composer composer init # 安装Behat composer require --dev behat/behat # 初始化Behat项目结构 vendor/bin/behat --init
项目结构
初始化后,Behat会创建以下结构:
my-project/
├── features/
│ ├── bootstrap/
│ │ └── FeatureContext.php
│ └── *.feature
├── vendor/
├── behat.yml
└── composer.json
创建Feature文件
示例功能:用户登录
features/login.feature
Feature: 用户登录
作为用户
我需要能够登录系统
以便访问我的账户
Scenario: 使用正确的凭据登录
Given 我在登录页面
When 我输入用户名 "john@example.com"
And 我输入密码 "password123"
And 我点击登录按钮
Then 我应该看到欢迎消息 "欢迎,John"
And 我应该被重定向到仪表盘
Scenario: 使用错误的凭据登录
Given 我在登录页面
When 我输入用户名 "john@example.com"
And 我输入密码 "wrongpassword"
And 我点击登录按钮
Then 我应该看到错误消息 "密码错误"
配置behat.yml
behat.yml
default:
autoload:
'': '%paths.base%/features/bootstrap'
suites:
default:
paths:
- '%paths.base%/features'
contexts:
- FeatureContext
extensions:
Behat\MinkExtension:
base_url: http://localhost
browser_name: chrome
sessions:
default:
selenium2:
wd_host: http://localhost:9515
编写FeatureContext
features/bootstrap/FeatureContext.php
<?php
use Behat\Behat\Context\Context;
use Behat\Gherkin\Node\TableNode;
use Behat\MinkExtension\Context\MinkContext;
class FeatureContext extends MinkContext implements Context
{
private array $users = [];
private string $currentUser = '';
public function __construct()
{
// 初始化测试数据
$this->users = [
'john@example.com' => [
'password' => 'password123',
'name' => 'John'
]
];
}
/**
* @Given 我在登录页面
*/
public function iAmOnLoginPage()
{
$this->visit('/login');
}
/**
* @When 我输入用户名 :username
*/
public function iEnterUsername($username)
{
$this->fillField('email', $username);
$this->currentUser = $username;
}
/**
* @When 我输入密码 :password
*/
public function iEnterPassword($password)
{
$this->fillField('password', $password);
}
/**
* @When 我点击登录按钮
*/
public function iClickLoginButton()
{
$this->pressButton('login');
}
/**
* @Then 我应该看到欢迎消息 :message
*/
public function iShouldSeeWelcomeMessage($message)
{
$this->assertPageContainsText($message);
}
/**
* @Then 我应该被重定向到仪表盘
*/
public function iShouldBeRedirectedToDashboard()
{
$this->assertPageAddress('/dashboard');
}
/**
* @Then 我应该看到错误消息 :message
*/
public function iShouldSeeErrorMessage($message)
{
$this->assertPageContainsText($message);
}
/**
* @Given 存在以下用户
*/
public function thereAreUsers(TableNode $table)
{
foreach ($table as $row) {
$this->users[$row['email']] = [
'password' => $row['password'],
'name' => $row['name']
];
}
}
}
运行Behat测试
# 运行所有测试 vendor/bin/behat # 运行指定文件 vendor/bin/behat features/login.feature # 运行指定场景 vendor/bin/behat features/login.feature:8 # 带格式化输出 vendor/bin/behat --format=pretty # 严格模式 vendor/bin/behat --strict
使用数据表
features/products.feature
Feature: 产品管理
作为管理员
我需要管理产品
以便更新商城信息
Scenario: 添加多个产品
Given 管理员已登录
When 我添加以下产品:
| 名称 | 价格 | 库存 |
| 苹果 | 5.00 | 100 |
| 香蕉 | 3.50 | 200 |
| 橙子 | 4.00 | 150 |
Then 产品列表应该包含 3 个产品
ProductContext.php
<?php
use Behat\Behat\Context\Context;
use Behat\Gherkin\Node\TableNode;
class ProductContext implements Context
{
private array $products = [];
/**
* @When 我添加以下产品:
*/
public function iAddProducts(TableNode $table)
{
foreach ($table as $row) {
$this->products[] = [
'name' => $row['名称'],
'price' => (float)$row['价格'],
'stock' => (int)$row['库存']
];
}
}
/**
* @Then 产品列表应该包含 :count 个产品
*/
public function productListShouldContain($count)
{
$actualCount = count($this->products);
if ($actualCount !== (int)$count) {
throw new \Exception("Expected $count products, got $actualCount");
}
}
}
使用正则表达式
/**
* @When /^我输入(用户名|密码) "([^"]*)"$/
*/
public function iEnterField($field, $value)
{
if ($field === '用户名') {
$this->fillField('email', $value);
} else {
$this->fillField('password', $value);
}
}
高级特性
场景大纲(Scenario Outline)
Feature: 计算器
作为用户
我需要使用计算器
以便进行数学运算
Scenario Outline: 加法运算
Given 我输入 <num1>
And 我输入 <num2>
When 我执行加法
Then 结果应该是 <result>
Examples:
| num1 | num2 | result |
| 1 | 2 | 3 |
| 10 | 20 | 30 |
| 5 | 7 | 12 |
后台(Background)
Feature: 用户管理
Background:
Given 管理员已登录
And 存在以下用户:
| name | email |
| John | john@test.com |
| Jane | jane@test.com |
Scenario: 查看用户列表
When 我访问用户列表
Then 我应该看到 2 个用户
标签(Tags)
Feature: 复杂功能
@smoke @critical
Scenario: 关键功能测试
Given 基础配置
And 额外配置
@wip @slow
Scenario: 开发中功能
Given 开发中的功能
运行带标签的测试:
vendor/bin/behat --tags=@smoke vendor/bin/behat --tags="@wip&&~@slow"
最佳实践
- 使用清晰的语言:Feature文件应使用业务语言,避免技术细节
- 保持步骤简洁:每个步骤只做一件事
- 使用数据驱动:利用Scenario Outline减少重复
- 维护测试数据:使用Fixture或Factory模式
- 合理的目录结构:按功能模块组织Feature文件
features/
├── authentication/
│ ├── login.feature
│ └── registration.feature
├── products/
│ ├── create.feature
│ ├── edit.feature
│ └── delete.feature
└── bootstrap/
└── FeatureContext.php
与CI/CD集成
GitHub Actions (.github/workflows/behat.yml)
name: Behat Tests
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: shivammathur/setup-php@v2
with:
php-version: '8.0'
- run: composer install
- run: vendor/bin/behat
Behat提供了一套强大的BDD测试框架,主要优势:
- 业务人员和开发人员可以共享相同语言
- 自动生成文档
- 易于维护
- 强类型断言
Behat不只是测试工具,更是沟通工具,能帮助团队更好地理解需求。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播