使用Codeception进行Yii2的单元测试(二)测试用例(测试model类为例)
一、生成测试文件
比如说我的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类难道要一个个手动生成测试类;如果我们项目文件结构有所改变的话也会会遇到一些问题。不过没关系,我们再接下来的几篇文章里会介绍相关的内容。