测试覆盖率
./vendor/bin/phpunit --coverage-html ./report
api文档创建
composer require --dev mpociot/laravel-apidoc-generator
php文档生成
测试环境
预览环境
开发环境
本地部署开发环境,开发后,git按照功能做分支,推送到开发分支,通过审核后自动化测试并生成报告,审核通过后推送到预览环境,预览环境无错误后,推送到主分支,自动部署到生产环境。生产环境使用容器云。自动化版本号,以及发布的版本。考虑如何实现灰度发布。基于容器编排来实现。
所有基础设施,区分为开发,测试,预览,生产。使用脚本进行部署。
Laravel 单元测试 方法列表
单元测试Demo
assertTrue(true);
}
}
创建测试
// 在 Feature 目录下创建一个测试类...
php artisan make:test UserTest
// 在 Unit 目录下创建一个测试类...
php artisan make:test UserTest --unit
运行方法
Http测试方法
$response = $this->get('/');
$response->assertStatus(200);// 确定返回状态为200
$response = $this->withHeaders(['X-Header' => 'Value',])
->json('POST', '/user', ['name' => 'Sally']); // 自定义请求头
$response->assertStatus(201)->assertJson(['created' => true,]);
//Tip:运行测试时,CSRF 中间件会自动禁用。
$response = $this->get('/');
$response->dumpHeaders(); // 调试响应
$response->dump();
$response = $this->withSession(['foo' => 'bar'])->get('/');
$user = factory(User::class)->create();
$response = $this->actingAs($user) //指定当前用户为已经认证过的用户 $this->actingAs($user, 'api')
->withSession(['foo' => 'bar'])
->get('/');
//测试 JSON APIs: 方法 json, get, post, put, patch,和 delete
$response = $this->json('POST', '/user', ['name' => 'Sally']);
$response->assertStatus(201)->assertJson(['created' => true,]);
//验证 JSON 完全匹配
$response = $this->json('POST', '/user', ['name' => 'Sally']);
$response->assertStatus(201)
->assertExactJson([
'created' => true,
]);
//测试文件上传 头像上传表单测试:
Storage::fake('avatars');
$file = UploadedFile::fake()->image('avatar.jpg');
$response = $this->json('POST', '/avatar', [
'avatar' => $file,
]);
// Assert the file was stored...
Storage::disk('avatars')->assertExists($file->hashName());
// Assert a file does not exist...
Storage::disk('avatars')->assertMissing('missing.jpg');
//虚拟文件制定
UploadedFile::fake()->image('avatar.jpg', $width, $height)->size(100);
//create方法可以创建其他文件
UploadedFile::fake()->create('document.pdf', $sizeInKilobytes);
//可用断言 确定
//Laravel 给 PHPUnit 测试提供了各种各样的常用断言方法。可从 json, get, post, put,和 delete 测试方法中访问这些断言:
assertCookie
assertCookieExpired
assertCookieNotExpired
assertCookieMissing
assertDontSee
assertDontSeeText
assertExactJson
assertForbidden
assertHeader
assertHeaderMissing
assertJson
assertJsonCount
assertJsonFragment
assertJsonMissing
assertJsonMissingExact
assertJsonMissingValidationErrors
assertJsonStructure
assertJsonValidationErrors
assertLocation
assertNotFound
assertOk
assertPlainCookie
assertRedirect
assertSee
assertSeeInOrder
assertSeeText
assertSeeTextInOrder
assertSessionHas
assertSessionHasInput
assertSessionHasAll
assertSessionHasErrors
assertSessionHasErrorsIn
assertSessionHasNoErrors
assertSessionDoesntHaveErrors
assertSessionMissing
assertStatus
assertSuccessful
assertUnauthorized
assertViewHas
assertViewHasAll
assertViewIs
assertViewMissing
//断言响应中包含给定的 cookie:
$response->assertCookie($cookieName, $value = null);
//断言响应中包含了给定的 cookie 且它已过期:
$response->assertCookieExpired($cookieName);
//断言响应中包含了给定的 cookie 且它未过期:
$response->assertCookieNotExpired($cookieName);
//断言响应中不包含给定的 cookie:
$response->assertCookieMissing($cookieName);
//断言响应中不包含给定的字符串:
$response->assertDontSee($value);
//断言给定字符串不包含在响应文本中:
$response->assertDontSeeText($value);
//断言响应中包含的数据与给定的 JSON 数据完全匹配:
$response->assertExactJson(array $data);
//断言响应中有禁止状态码:
$response->assertForbidden();
//断言响应中有给定的包头:
$response->assertHeader($headerName, $value = null);
//断言响应中没有给定的报头:
$response->assertHeaderMissing($headerName);
//断言响应包含给定的 JSON 数据:
$response->assertJson(array $data);
//断言响应 JSON 中有一个数组,其中包含给定键的预期元素数量:
$response->assertJsonCount($count, $key = null);
//断言响应包含给定 JSON 片段:
$response->assertJsonFragment(array $data);
//断言响应未包含给定的 JSON 片段:
$response->assertJsonMissing(array $data);
//断言响应不包含确切的 JSON 片段:
$response->assertJsonMissingExact(array $data);
//断言响应没有给定键的 JSON 验证错误:
$response->assertJsonMissingValidationErrors($keys);
//断言响应具有给定的 JSON 结构:
$response->assertJsonStructure(array $structure);
//断言响应具有给定键的给定 JSON 验证错误:
$response->assertJsonValidationErrors(array $data);
//断言响应在 Location 头部中具有给定的 URI 值:
$response->assertLocation($uri);
//断言响应具有未找到状态码:
$response->assertNotFound();
//断言响应有 200 状态码:
$response->assertOk();
//断言响应包含给定的 cookie (未加密):
$response->assertPlainCookie($cookieName, $value = null);
//断言响应会重定向到给定的 URI:
$response->assertRedirect($uri);
//断言给定的字符串包含在响应中:断言响应中有序包含了给定的字符串:
$response->assertSee($value);
//断言响应中有序包含了给定的字符串:
$response->assertSeeInOrder(array $values);
//断言给定的字符串包含在响应文本中:
$response->assertSeeText($value);
//断言给定的字符串有序包含在响应文本中:
$response->assertSeeTextInOrder(array $values);
//断言 session 中包含给定的数据:
$response->assertSessionHas($key, $value = null);
//断言 session 中有给定值数组:
$response->assertSessionHasInput($key, $value = null);
//断言 session 中有给定值列表:
$response->assertSessionHasAll(array $data);
//断言 session 中包含一个给定字段的错误:
$response->assertSessionHasErrors(array $keys, $format = null, $errorBag = 'default');
//断言 session 中具有给定的错误:
$response->assertSessionHasErrorsIn($errorBag, $keys = [], $format = null);
//断言 session 没有错误:
$response->assertSessionHasNoErrors();
//断言 session 没有给定键错误:
$response->assertSessionDoesntHaveErrors($keys = [], $format = null, $errorBag = 'default');
//断言 session 中不包含给定键:
$response->assertSessionMissing($key);
//断言响应中具有给定的状态码:
$response->assertStatus($code);
//断言响应中有成功的状态码:
$response->assertSuccessful();
//断言响应中有未授权的(401)状态码:
$response->assertUnauthorized();
//断言响应视图是一段给定的数据:
$response->assertViewHas($key, $value = null);
//断言响应视图具有给定的数据列表:
$response->assertViewHasAll(array $data);
//断言路由返回给定的视图:
$response->assertViewIs($value);
//断言响应视图缺少一段绑定数据:
$response->assertViewMissing($key);
//Laravel 还为你的 PHPUnit 测试提供了各种与身份验证相关的断言:
Method Description
//断言此用户已被认证。
$this->assertAuthenticated($guard = null);
//断言此用户未被认证。
$this->assertGuest($guard = null);
//断言给定的用户被认证。
$this->assertAuthenticatedAs($user, $guard = null);
//断言给定的凭证有效。
$this->assertCredentials(array $credentials, $guard = null);
//断言给定的凭证无效。
$this->assertInvalidCredentials(array $credentials, $guard = null);
命令行测试方法
// 除了简化 HTTP 测试之外, Laravel 为测试用户输入的控制台应用提供了简单的 API 。
// 期望输入 / 输出
Artisan::command('question', function () {
$name = $this->ask('What is your name?');
$language = $this->choice('Which language do you program in?', [
'PHP',
'Ruby',
'Python',
]);
$this->line('Your name is '.$name.' and you program in '.$language.'.');
});
/**
* 测试控制台命令
*
* @return void
*/
public function test_console_command()
{
//确定控制台命令的输入和输出是正确的.
$this->artisan('question')
->expectsQuestion('What is your name?', 'Taylor Otwell') //输入
->expectsQuestion('Which language do you program in?', 'PHP') //输入
->expectsOutput('Your name is Taylor Otwell and you program in PHP.') //输出
->assertExitCode(0);
}
数据库测试方法
//Laravel 提供了各种有用的工具,可以更轻松地测试数据库驱动的应用程序。 首先,你可以使用 assertDatabaseHas 辅助函数,来断言数据库中是否存在与指定条件互相匹配的数据。 例如,如果我们想要验证 users 表中是否存在 email 值为 [email protected] 的数据,你可以执行以下操作:
public function testDatabase()
{
// 调用应该程序...
$this->assertDatabaseHas('users', [
'email' => '[email protected]',
]);
}
//生成模型工厂
php artisan make:factory PostFactory
//--model 选项可用于指示工厂创建的模型的名称。 此选项将使用给定模型预填充生成的工厂文件:
php artisan make:factory PostFactory --model=Post
//每次测试后重置数据库 : 在每次测试后重置数据库是很有用的,这样前一次测试的数据不会干扰后续测试。 RefreshDatabase trait 会采用最优化的方法来迁移测试数据库,这取决于你使用的是内存数据库还是传统数据库。 在测试类中引用这个 trait ,一切都将为你处理:
class ExampleTest extends TestCase
{
use RefreshDatabase; //使用测试环境变量时可以使用这个trait
}
//创建模型工厂: 进行测试时,运行测试之前常常需要插入一些数据到数据库中。当你创建测试数据时,除了手动设置每个字段的值,Laravel 还可以使用 Eloquent 模型 的工厂来设置每个属性的默认值。在开始之前, 你可以先看一下应用程 database/factories/UserFactory.php 的文件。 开箱即用,这个文件包含一个模型工厂定义:
use Illuminate\Support\Str;
use Faker\Generator as Faker;
$factory->define(App\User::class, function (Faker $faker) {
return [
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'email_verified_at' => now(),
'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret
'remember_token' => Str::random(10),
];
});
//在这个模型工厂定义的闭包中,你可以返回模型上所有属性的默认测试值。闭包将接受 PHP 函数库 Faker 的一个实例,它允许你便捷的生成各种随机数据来进行测试。
//你也可以为每个模型创建一个工厂文件以便实现更好的组织。 例如,你可以自 database/factories 目录下创建 UserFactory.php 和 CommentFactory.php 文件。 Laravel 将自动加载 factories 目录下的所有文件。
//工厂状态
//工厂状态可以让你任意组合你的模型工厂,仅需要做出适当差异化的修改,就可以达到让模型拥有多种不同的状态。例如, 你的 User 模型中可以修改某个默认属性值来达到标识一种 delinquent 状态。你可以使用 state 方法来进行这种状态转换。对于简单的工厂状态,你可以传入要修改的属性数组:
$factory->state(App\User::class, 'delinquent', [
'account_status' => 'delinquent',
]);
//如果你的工厂状态需要计算或者使用 $faker 实例。你可以使用闭包方法来实现状态属性的修改:
$factory->state(App\User::class, 'address', function ($faker) {
return [
'address' => $faker->address,
];
});
//工厂回调
//工厂回调是使用 afterMaking 和 afterCreating 方法注册的,并且允许你在创建模型之后执行其他任务。例如,可以使用回调将附加模型与创建的模型相关联:
$factory->afterMaking(App\User::class, function ($user, $faker) {
// ...
});
$factory->afterCreating(App\User::class, function ($user, $faker) {
$user->accounts()->save(factory(App\Account::class)->make());
});
//你还可以为 工厂状态 定义回调:
$factory->afterMakingState(App\User::class, 'delinquent', function ($user, $faker) {
// ...
});
$factory->afterCreatingState(App\User::class, 'delinquent', function ($user, $faker) {
// ...
});
使用模型工厂
创建模型
模型工厂定义后,就可以在测试或者是数据库的填充文件中,通过全局的 factory 函数来生成模型实例。因此,先让我们来看看几个模型创建的例子。 首先,我们将使用 make 方法创建模型但不将他们保存至数据库:
public function testDatabase()
{
$user = factory(App\User::class)->make();
// 在测试中使用模型...
}
你也可以创建一个含有多个模型的集合,或创建一个指定类型的模型:
// 创建三个 App\User 实例...
$users = factory(App\User::class, 3)->make();
应用状态
你也可将任何状态应用于模型。若将多个状态转换应用于模型,你应当为每个状态指定名称:
$users = factory(App\User::class, 5)->states('delinquent')->make();
$users = factory(App\User::class, 5)->states('premium', 'delinquent')->make();
覆盖属性
如果要覆盖模型的某些默认值,你可以将一组值传递给 make 方法。 这样的话只有指定的值才会被替换,而其余值仍为工厂指定的默认值:
$user = factory(App\User::class)->make([
'name' => 'Abigail',
]);
Tip:使用工厂创建模型时,将自动禁用 批量赋值 。
持久化模型
create 方法创建模型实例的同时还调用了把记录写入数据库的 save 方法:
public function testDatabase()
{
// 创建单个 App\User 实例...
$user = factory(App\User::class)->create();
// 创建 3 个 App\User 实例..
$users = factory(App\User::class, 3)->create();
// 在测试中使用模型...
}
传入一个数组给 create 方法重写模型的属性:
$user = factory(App\User::class)->create([
'name' => 'Abigail',
]);
关联模型
在这个例子中,我们将为模型创建关联。使用 create 方法创建多模型时,返回一个 Eloquent 实例集合,这样就可以在集合上使用 each 等便捷方法:
$users = factory(App\User::class, 3)
->create()
->each(function ($user) {
$user->posts()->save(factory(App\Post::class)->make());
});
你可以使用 createMany 方法创建多个相关模型:
$user->posts()->createMany(
factory(App\Post::class, 3)->make()->toArray()
);
关联 & 属性闭包
模型工厂定义时,也可以使用闭包里的属性来给模型添加关联。 例如,创建 Post 实例时,同时创建 User 实例,可以这样做:
$factory->define(App\Post::class, function ($faker) {
return [
'title' => $faker->title,
'content' => $faker->paragraph,
'user_id' => function () {
return factory(App\User::class)->create()->id;
},
];
});
这些闭包接收一个包含工厂属性的数组:
$factory->define(App\Post::class, function ($faker) {
return [
'title' => $faker->title,
'content' => $faker->paragraph,
'user_id' => function () {
return factory(App\User::class)->create()->id;
},
'user_type' => function (array $post) {
return App\User::find($post['user_id'])->type;
},
];
});
在测试中使用数据填充
如果你希望在测试期间使用 数据填充 填充数据库,则可以使用 seed 方法。默认情况下, seed 方法将返回 DatabaseSeeder, 它会结束其他的数据填充器。 或者,将指定的数据填充器的类名传递给 seed 方法:
seed();
// 运行单个数据填充器...
$this->seed(OrderStatusesTableSeeder::class);
// ...
}
}
//上面鬼扯了这么多,下面是基于数据库的断言
Method Description
$this->assertDatabaseHas($table, array $data); 断言数据库表中包含给定的数据。
$this->assertDatabaseMissing($table, array $data); 断言数据库中的表不包含给定数据。
$this->assertSoftDeleted($table, array $data); 断言给定记录已被软删除。
测试模拟器 Mocking
//在 Laravel 应用程序测试中,你可能希望「模拟」应用程序的某些功能的行为,从而避免该部分在测试中真正执行。例如:在控制器执行过程中会触发事件,从而避免该事件在测试控制器时真正执行。这允许你在仅测试控制器 HTTP 响应的情况时,而不必担心触发事件。当然,你也可以在单独的测试中测试该事件逻辑。
//Laravel 针对事件、任务和 Facades 的模拟,提供了开箱即用的辅助函数。这些函数基于 Mocker 封装而成,使用非常方便,无需手动调用复杂的 Mockery 函数。当然你也可以使用 Mockery 或者使用 PHPUnit 创建自己的模拟器。
//模拟对象
//当模拟一个对象将通过 Laravel 的服务容器注入到应用中时,你将需要将模拟实例作为 instance 绑定到容器中。这将告诉容器使用对象的模拟实例,而不是构造对象的真身:
use Mockery;
use App\Service;
$this->instance(Service::class, Mockery::mock(Service::class, function ($mock) {
$mock->shouldReceive('process')->once();
}));
//为了让以上过程更加便捷,你可以使用 Laravel 的基本测试用例类提供 mock 方法:
use App\Service;
$this->mock(Service::class, function ($mock) {
$mock->shouldReceive('process')->once();
});
//同样,如果你想侦查一个对象,Laravel 的基本测试用例类提供了一个便捷的 spy 方法作为 Mockery::spy 的替代方法:
use App\Service;
$this->spy(Service::class, function ($mock) {
$mock->shouldHaveReceived('process');
});
//任务模拟 (测试Job用)
//作为模拟的替代方式,你可以使用 Bus Facade 的 fake 方法来防止任务被真正分发执行。使用 fake 的时候,断言一般出现在测试代码的后面:
order->id === $order->id;
});
// 断言任务并未分发...
Bus::assertNotDispatched(AnotherJob::class);
}
}
//事件模拟 (测试Event用)
//作为 mock 的替代方法,你可以使用 Event Facade 的 fake 方法来模拟事件监听,测试的时候并不会真正触发事件监听器。然后你就可以测试断言事件运行了,甚至可以检查他们接收的数据。使用 fake 的时候,断言一般出现在测试代码的后面:
order->id === $order->id;
});
// 断言一个事件被发送了两次...
Event::assertDispatched(OrderShipped::class, 2);
// 未分配断言事件...
Event::assertNotDispatched(OrderFailedToShip::class);
}
}
//注意:调用 Event::fake() 后不会执行事件监听。所以,你基于事件的测试必须使用工厂模型,例如,在模型的 creating 事件中创建 UUID ,你应该调用 Event::fake() 之后 使用工厂模型。
//模拟事件的子集
//如果你只想为特定的一组事件模拟事件监听器,你可以将它们传递给 fake 或 fakeFor 方法:
/**
* 测试订单流程。
*/
public function testOrderProcess()
{
Event::fake([
OrderCreated::class,
]);
$order = factory(Order::class)->create();
Event::assertDispatched(OrderCreated::class);
// 其他事件照常发送...
$order->update([...]);
}
//Scoped 事件模拟
//如果你只想为部分测试模拟事件监听,则可以使用 fakeFor 方法:
create();
Event::assertDispatched(OrderCreated::class);
return $order;
});
// 事件按正常方式发送,观察者将运行...
$order->update([...]);
}
}
//邮件模拟
//你可以是用 Mail Facade 的 fake 方法来模拟邮件发送,测试时不会真的发送邮件,然后你可以断言 mailables 发送给了用户,甚至可以检查他们收到的内容。使用 fakes 时,断言一般放在测试代码的后面:
order->id === $order->id;
});
// 断言一条发送给用户的消息...
Mail::assertSent(OrderShipped::class, function ($mail) use ($user) {
return $mail->hasTo($user->email) &&
$mail->hasCc('...') &&
$mail->hasBcc('...');
});
// 断言邮件被发送两次...
Mail::assertSent(OrderShipped::class, 2);
// 断言没有发送邮件...
Mail::assertNotSent(AnotherMailable::class);
}
}
//如果你用后台任务执行邮件发送队列,你应该是用 assertQueued 代替 assertSent :
Mail::assertQueued(...);
Mail::assertNotQueued(...);
//通知模拟 (测试通知)
//你可以使用 Notification Facade 的 fake 方法来模拟通知的发送,测试时并不会真的发出通知。然后你可以断言 notifications 发送给了用户,甚至可以检查他们收到的内容。使用 fakes 时,断言一般放在测试代码后面:
order->id === $order->id;
}
);
// 断言向给定用户发送了通知...
Notification::assertSentTo(
[$user], OrderShipped::class
);
// 断言没有发送通知...
Notification::assertNotSentTo(
[$user], AnotherNotification::class
);
// 断言通过 Notification::route() 方法发送通知...
Notification::assertSentTo(
new AnonymousNotifiable, OrderShipped::class
);
}
}
# 队列模拟 (测试队列)
// 为模拟替代方案,你可以使用 Queue Facade 的 fake 方法避免把任务真的放到队列中执行。然后你就可以断言任务已经被推送入队列了,甚至可以检查它们收到的数据。使用 fakes 时,断言一般放在测试代码的后面:
order->id === $order->id;
});
// 断言任务进入了指定队列...
Queue::assertPushedOn('queue-name', ShipOrder::class);
// 断言任务进入2次...
Queue::assertPushed(ShipOrder::class, 2);
// 断言没有一个任务进入队列...
Queue::assertNotPushed(AnotherJob::class);
// 断言任务是由特定的通道发送的..
Queue::assertPushedWithChain(ShipOrder::class, [
AnotherJob::class,
FinalJob::class
]);
}
}
//存储模拟
//你可以使用 Storage Facade 的 fake 方法,轻松的生成一个模拟磁盘,结合 UploadedFile 类的文件生成工具,极大的简化了文件上传测试。例如:
json('POST', '/photos', [
UploadedFile::fake()->image('photo1.jpg'),
UploadedFile::fake()->image('photo2.jpg')
]);
// 断言文件已存储...
Storage::disk('photos')->assertExists('photo1.jpg');
Storage::disk('photos')->assertExists(['photo1.jpg', 'photo2.jpg']);
// 断言文件不存在...
Storage::disk('photos')->assertMissing('missing.jpg');
Storage::disk('photos')->assertMissing(['missing.jpg', 'non-existing.jpg']);
}
}
//Tip: 默认情况下,fake 方法将删除临时目录下所有文件。如果你想保留这些文件,你可以使用 「persistentFake」。
//Facades
//与传统静态方法调用不同的是,facades 也可以被模拟。相较传统的静态方法而言,它具有很大的优势,即便你使用依赖注入,可测试性不逊半分。在测试中,你可能想在控制器中模拟对 Laravel Facade 的调用。比如下面控制器中的行为:
once()
->with('key')
->andReturn('value');
$response = $this->get('/users');
// ...
}
}
//注意:你不能模拟 Request Facade 。相反,在运行测试时如果需要传入指定参数,请使用 HTTP 辅助函数,比如 get 和 post 。同理,请在测试时通过调用 Config::set 来模拟 Config Facade。
看完觉得还是不知道怎么用测试.这文档写的
看来需要看phpunit支持的断言.
# 布尔类型
方法名 含义 参数 返回值
assertTrue 断言为真
assertFalse 断言为假
# NULL类型
方法名 含义 参数 返回值
assertNull 断言为NULL
assertNotNull 断言非NULL
#数字类型
方法名 含义 参数 返回值
assertEquals 断言等于
assertNotEquals 断言大于
assertGreaterThan 断言不等于
assertGreaterThanOrEqual 断言大于等于
assertLessThan 断言小于
assertLessThanOrEqual 断言小于等于
# 字符类型
方法名 含义 参数 返回值
assertEquals 断言等于
assertNotEquals 断言不等于
assertContains 断言包含
assertNotContains 断言不包含
assertContainsOnly 断言小于
assertLessThanOrEqual 断言只包含
assertNotContainsOnly 断言不只包含
#数组类型
方法名 含义 参数 返回值
assertEquals 断言等于
assertNotEquals 断言不等于
assertArrayHasKey 断言有键
assertArrayNotHasKey 断言没有键
assertContains 断言包含
assertNotContains 断言不包含
assertContainsOnly 断言只包含
assertNotContainsOnly 断言不只包含
#对象类型
方法名 含义 参数 返回值
assertAttributeContains 断言属性包含
assertAttributeContainsOnly 断言属性只包含
assertAttributeEquals 断言属性等于
assertAttributeGreaterThan 断言属性大于
assertAttributeGreaterThanOrEqual 断言属性大于等于
assertAttributeLessThan 断言属性小于
assertAttributeLessThanOrEqual 断言属性小于等于
assertAttributeNotContains 断言不包含
assertAttributeNotContainsOnly 断言属性不只包含
assertAttributeNotEquals 断言属性不等于
assertAttributeNotSame 断言属性不相同
assertAttributeSame 断言属性相同
assertSame 断言类型和值都相同
assertNotSame 断言类型或值不相同
assertObjectHasAttribute 断言对象有某属性
assertObjectNotHasAttribute 断言对象没有某属性
#class类型
方法名 含义 参数 返回值
assertClassHasAttribute 断言类有某属性
assertClassHasStaticAttribute 断言类有某静态属性
assertClassNotHasAttribute 断言类没有某属性
assertClassNotHasStaticAttribute 断言类没有某静态属性
#文件相关
方法名 含义 参数 返回值
assertFileEquals 断言文件内容等于
assertFileExists 断言文件存在
assertFileNotEquals 断言文件内容不等于
assertFileNotExists 断言文件不存在
#XML相关
方法名 含义 参数 返回值
assertXmlFileEqualsXmlFile 断言XML文件内容相等
assertXmlFileNotEqualsXmlFile 断言XML文件内容不相等
assertXmlStringEqualsXmlFile 断言XML字符串等于XML文件内容
assertXmlStringEqualsXmlString 断言XML字符串相等
assertXmlStringNotEqualsXmlFile 断言XML字符串不等于XML文件内容
assertXmlStringNotEqualsXmlString 断言XML字符串不相等
以及具体的测试用例.不过基本上知道了可以对API,以及html页面进行集成测试.对单个函数进行单元测试.
整一个跟jquery文档一样的参考吧.点哪个看哪个.
一个实例集合.
名称:签到任务,领金币。
https://blog.51cto.com/janephp/1332575
clearTask($this->testUid, 'sign');
//清除签到表,清除用户的连续签到天和最后签到时间
$signModel = new GuaziSignModel();
$signModel->getCollection()->update(array('uid' => $this->testUid ), array('$unset' => array ('last_time' => 1, 'sign_time' => 1)));
}
/**
* 这个函数用来断言上一步清除任务状态是否完成
*/
public function testEmpty(){
//断言是否任务状态已清空
$objSignTask = Task_Factory::factory('sign');
$signStatus = $objSignTask->getStatus($this->testUid);
//清除完成,则任务状态归零,所以用0来断言
$this->assertEquals(0, $signStatus);
//断言是否任务已清空
$signModel = new GuaziSignModel();
$arrsign = $signModel->getSignByUid($this->testUid);
//这里因为清空是直接清除了字段,所以用NULL来断言
$this->assertNull($arrsign['n_t']);
$this->assertNull($arrsign['t']);
}
/**
* 这个函数是签到数据的供给器,主要是为了模拟签到连续的天数,为下面的testSign提供数据,这里
* 需要了解数据供给器的用法@dataProvider
* @return array
*/
public function dataProducer() {
//提供签到数据
//第1个参数是签到时间,第2个是连续签到的天数,第3个是任务的完成状态
return array(
array('2013-11-25 19:30', 1, 1),
array('2013-11-26 18:30', 2, 2),
array('2013-11-27 10:30', 3, 3),
array('2013-11-28 23:59', 4, 4),
array('2013-11-29 22:59', 5, 4),
);
}
/**
* @dataProvider dataProducer
*/
public function testSign($nowTime,$signCount,$taskStatus)
{
//循环接收dataProducer给的值开始执行任务,3个参数就是上面数组的个数
$now = strtotime($nowTime);
$signModel = new GuaziSignModel();
//更新任务表状态并断言
$objSignTask = Task_Factory::factory('sign');
//更新任务状态,当然内部会区分每一步不同的操作
$doTaskRes = $objSignTask->doTaskForPhpunit($this->testUid, $now);
//断言执行结果
$this->assertEquals(1, $doTaskRes);
//获取任务状态
$signStatus = $objSignTask->getStatus($this->testUid);
//断言任务状态
$this->assertEquals($taskStatus, $signStatus);
//更新签到表并断言
$ret = $signModel->updateLastSign($this->testUid,$now);
//断言连续签到天数
$this->assertCount($signCount, $ret['t']);
}
}
$params = ['phone' => $phone];
$with = ['user', 'type'];
$result = $this->user->listAccountWithByParamArray($params, $with);
$this->assertArrayHasKey('data', $result);
$account = $result['data'][0];
$this->assertArrayHasKey('nickname', $account);
$this->assertArrayHasKey('user_id', $account);
$this->assertArrayHasKey('is_available', $account);
Laravel 测试驱动开发 -- 正向单元测试
[7](javascript:;)[1](javascript:;)2
Laravel 测试驱动开发 -- 反向单元测试
[1](javascript:;)[1](javascript:;)0
PHP Parser 简介和应用 - 为你的代码自动补全单元测试
[14](javascript:;)[6](javascript:;)3
(TDD 构建 Laravel 论坛笔记 测试驱动开发)
[https://learnku.com/docs/forum-in-laravel-tdd]
(好吧.到这里应该已经找到一些概念了.好好写测试.)
下面我来一个实战.