一、生成测试文件
比如说我的models有一个需要测试得AdminUser类,我需要生成相应得测试文件,那么我们可以使用下面得命令生成相应得测试文件
vendor\bin\codecept generate:test unit \models\AdiminUser
二、测试用例的编写
我们生成的测试用例是这个样子的(AdiminUserTest.php):
namespace models;
/**
* Class AdiminUserTest by gy
* @package models
*/
class AdiminUserTest extends \Codeception\Test\Unit
{
/**
* @var \UnitTester
*/
protected $tester;
protected function _before()
{
}
protected function _after()
{
}
// tests
public function testSomeFeature()
{
}
}
现在我们来修改这个文件,使它能完成简单的处理。这里的assertTrue方法,是用来做真假断言用的。当然还有很多其他种类的断言,如:assertInternalType;assertEquals;assertInstanceOf……可以查看更多断言详细
namespace models;
/**
* Class AdiminUserTest by gy
* @package models
*/
class AdiminUserTest extends \Codeception\Test\Unit
{
/**
* @var \UnitTester
*/
protected $tester;
protected function _before()
{
}
protected function _after()
{
}
// tests
public function testSomeFeature()
{
$this->assertTrue(1==1);
}
public function testFunction1()
{
$this->assertTrue(3 > 1);
}
//这个是明显错误
public function testFunction2()
{
$this->assertTrue(3 < 1);
}
}
现在我们可以使用命令执行我们的测试用例了:
vendor\bin\codecept run unit \models\AdiminUserTest
执行结果如下所示(3个成功,1个失败),testFunction2有明显错误,改正以后会没有失败数量的
好了现在我们已经学会了简单的断言。但是,我们没有忘记,这个测试用例本意是要对AdminUser这个model类做单元测试的。接下来我们要真正的步入正题了。
三、对指定的类进行单元测试
首先我的AdminUser的类如下(AdminUser.php):
namespace app\models;
class AdminUser extends \yii\base\BaseObject implements \yii\web\IdentityInterface
{
public $id;
public $username;
public $password;
public $authKey;
public $accessToken;
private static $users = [
'100' => [
'id' => '100',
'username' => 'admin',
'password' => 'admin',
'authKey' => 'test100key',
'accessToken' => '100-token',
],
'101' => [
'id' => '101',
'username' => 'demo',
'password' => 'demo',
'authKey' => 'test101key',
'accessToken' => '101-token',
],
];
/**
* {@inheritdoc}
*/
public static function findIdentity($id)
{
return isset(self::$users[$id]) ? new static(self::$users[$id]) : null;
}
/**
* {@inheritdoc}
*/
public static function findIdentityByAccessToken($token, $type = null)
{
foreach (self::$users as $user) {
if ($user['accessToken'] === $token) {
return new static($user);
}
}
return null;
}
/**
* Finds user by username
*
* @param string $username
* @return static|null
*/
public static function findByUsername($username)
{
foreach (self::$users as $user) {
if (strcasecmp($user['username'], $username) === 0) {
return new static($user);
}
}
return null;
}
/**
* {@inheritdoc}
*/
public function getId()
{
return $this->id;
}
/**
* {@inheritdoc}
*/
public function getAuthKey()
{
return $this->authKey;
}
/**
* {@inheritdoc}
*/
public function validateAuthKey($authKey)
{
return $this->authKey === $authKey;
}
/**
* Validates password
*
* @param string $password password to validate
* @return bool if password provided is valid for current user
*/
public function validatePassword($password)
{
return $this->password === $password;
}
}
我们要在AdiminUserTest中去对上述的类做测试,第一步做的就是要能加载到该类。我们知道,现在大部分框架都是使用psr-4规则的/vendor/autoload.php来完成自动加载的,当然yii2和它的codeception也是一样的。这边是多说了一些,等我们后续遇到这个问题了,再详细说。
namespace models;
use app\models\AdminUser;
/**
* Class AdiminUserTest by gy
* @package models
*/
class AdiminUserTest extends \Codeception\Test\Unit
{
/**
* @var \UnitTester
*/
protected $tester;
protected function _before()
{
}
protected function _after()
{
}
// tests
public function testFindUserById()
{
expect_that($user = AdminUser::findIdentity(100));
expect($user->username)->equals('admin');
expect_not(AdminUser::findIdentity(999));
}
public function testFindUserByAccessToken()
{
expect_that($user = AdminUser::findIdentityByAccessToken('100-token'));
expect($user->username)->equals('admin');
expect_not(AdminUser::findIdentityByAccessToken('non-existing'));
}
public function testFindUserByUsername()
{
expect_that($user = AdminUser::findByUsername('admin'));
expect_not(AdminUser::findByUsername('not-admin'));
}
/**
* @depends testFindUserByUsername
*/
public function testValidateUser($user)
{
$user = AdminUser::findByUsername('admin');
expect_that($user->validateAuthKey('test100key'));
expect_not($user->validateAuthKey('test102key'));
expect_that($user->validatePassword('admin'));
expect_not($user->validatePassword('123456'));
}
}
expect_that: 假设为true
expect_not: 假设为false
和我们用assertFalse和assertTrue意义是一样的
好了,我们来执行命令吧。看看现在的会不会如我们设想的一般。
vendor\bin\codecept run unit \models\AdiminUserTest
4个测试方法,12个断言都没有问题,执行成功。
总结,至此我们的小小目标基本达成,生成测试文件,测试相关单元的目标基本都可以完成了。当然,我们还是有一些问题亟待解决的,比如说,我们用来测试的数据还是models的静态变量(不够真实);我们有100个model类难道要一个个手动生成测试类;如果我们项目文件结构有所改变的话也会会遇到一些问题。不过没关系,我们再接下来的几篇文章里会介绍相关的内容。