authors 是 vetted experts in their fields 和 write on topics in which they have demonstrated experience. All of our content is peer reviewed 和 validated by Toptal experts in the same field.
瓦西里•Koval
验证专家 在工程
20 的经验

Vasily is a web developer with more than nine years of extensive experience developing, 优化, 支持web应用程序.

阅读更多

专业知识

分享

在继续之前 Codeception 和PHP, we should cover the basics 和 start by explaining why we need testing in applications in the first place. Perhaps we could complete a project without wasting time on 测试, at least this time?

Sure, you don’t need 测试 for everything; for example, when you want to build yet another homepage. You probably don’t need 测试 when your project contains static pages linked by one router.

然而,在以下情况下,你确实需要测试:

  • 您的团队使用BDD/TDD.
  • 您的Git仓库包含多个提交.
  • 你是一个真正的专业人士,正在做一个严肃的项目.

你可以说你已经有了一个专门的测试部门, 执行测试并在需要时编写新测试的一组人. But, can you imagine how long bug fixing will take after you add new 功能ity to your project?

测试解决什么问题?

首先,让我们决定哪些问题可以通过测试来解决. 你不可能通过测试消除所有的错误, 但是你可以在测试用例中描述预期的行为. 错误可能在您的测试用例中. 即使在使用测试用例时,面条式代码仍然是面条式代码.

然而, 您可以确保您的代码之后会被修改(通过修复错误), 或者添加新功能), 因此,您的代码仍然不会出现测试中描述的错误. 除了, even well-written 测试 may sometimes be used in documentation because there you can see how typical scenarios unfold 和 check expected behavior. 我们可以说,测试是未来的一项小而关键的投资.

那么我们可以使用什么样的测试呢?

基本单元测试通常是不够的. 它们需要得到集成测试、功能测试和验收测试的支持.

基本单元测试通常是不够的. 它们需要得到集成测试、功能测试和验收测试的支持.
  • 单元测试: Low-level 测试 that check small pieces of your code - your class’ methods isolated from other code.
  • 集成开发测试: 集成测试检查应用程序的一部分, 它们可能包含几个类或方法, 但应该限制在一个功能上. 这个测试还应该检查不同的类是如何交互的.
  • 功能测试: Tests specific requests to your application: browser response, database changes 等等......。.
  • 验收测试: In most cases 验收 testing means checking if the application meets all client requirements.

To clarify, let’s say we illustrate the process with something tangible, such as a building. 建筑物是由构成墙壁的小块组成的. Each brick has to meet specified requirements; it has to withst和 the required load, 有特定的体积和形状, 等等......。. 这些是单元测试. The idea of integrational 测试 is to check how tightly 和 accurately the bricks adhere to each other, 它们是如何融入建筑的某个元素的. 功能测试可以比作在建筑物的一面墙上进行测试, 检查内部是否受到保护, 是否有可能透过窗户看到太阳. 验收 testing involves testing the entire building as a complete product: Open the door, 进去, 把门关上, 打开灯, 爬到二楼,看看楼外的花园.

满足Codeception

然而,这种划分是 有条件的 和 sometimes it is difficult to resist the temptation of mixing different kinds of 测试.

许多开发人员使用单元测试,并声称这就足够了. I used to be one such developer; I found using different systems for different types of 测试 too difficult 和 time-consuming. 不久前,我决定找一些比 PHPUnit); I wanted to be better at testing my code, 但我不想阅读和学习大量的文档并寻找陷阱. 我就是这样发现了Codeception. 起初, 我很怀疑, 就像我们经常遇到的新事物一样(这个项目已经5年了), 所以在技术上, 它不能被认为是“新的”)。, 但在摆弄了几天之后, 我的结论是,Codeception是一个非常有用和强大的系统.

那么如何安装Codeception呢? 这很简单:

$ 作曲家 require "codeception/codeception"
$ PHP vendor/bin/codecept bootstrap

安装完成后,您会发现一个名为 测试 在您的项目中,会有一些子文件夹名为 验收、功能单位. 看起来我们可以开始编写测试了. 很酷,但接下来呢?

现在,试着添加一个标准 验收 Hello World测试.

$ php vendor/bin/codecept

现在,我们得到一个验收测试文件测试/验收/HelloWorldCept.Php,包含以下内容:

wantTo('perform actions 和 see result');

默认变量,名为 $I, is not just a letter; it is a character. 进行测试的是什么?? 很明显,测试员. 这个测试者打开你网站的页面或类, 用它做点什么, 并向你展示其行为的最终结果. 你会看到什么是有效的,什么是错误的. 这就是这个天体被命名的原因 $I 以及为什么它包含调用 想(), 见() or amOnPage ().

因此,让我们像测试人员一样考虑检查页面可操作性的方法. 第一种方法是打开页面并搜索一个短语. 它证明该页面对访问者是可用的.

这应该很简单:

amOnPage('/');
$I->see('Welcome');

我们可以使用这个命令来运行Codeception的测试:

$ PHP vendor/bin/codecept run

我们马上就能看出有什么不对劲. 乍一看, 这条信息似乎太长太不清楚了, 但当我们更仔细地看, 一切都变得显而易见.

突然摔倒! 出了什么问题. 这就是测试的全部意义. 检查信息,找出错误,并从错误中吸取教训.

突然摔倒! 出了什么问题. 这就是测试的全部意义. 检查信息,找出错误,并从错误中吸取教训.

我们做了一个测试, 验收,它检测到一个错误:

验收测试(1)
Perform actions 和 see result (HelloWorldCept)                                                             Error

----------
1) Failed to perform actions 和 see result in HelloWorldCept (测试/验收/HelloWorldCept .php)
[GuzzleHttp\Exception\ConnectException] cURL error 6: Could not resolve host: 本地主机 (see http://curl.haxx.se / libcurl / c / libcurl-errors.html) 

这就是罪魁祸首: 本地主机 不可用.

下面是我们测试的场景步骤:

 1. $I->amOnPage("/")

好的,让我们打开测试/验收.套件.Yml和更改 url: http://本地主机/变成实际可用的东西. 在我的例子中,它是我的本地测试主机, url: http://local.codeception-article.com/

再次运行测试,这就是你应该得到的结果:

验收测试(1) ---------------------------------------------------------------------------------------
Perform actions 和   result (HelloWorldCept)                                                             Ok

万岁! 我们第一次成功的测试!

当然, amOnPage () 不是唯一可用的测试方法吗,我们只是把它挑出来作为我们的例子. 所有Codeception测试方法可分为以下几组:

  • 与页面交互: fillField (), selectOption (), submitForm (), click ()
  • 断言. 见(), dontSee (), seeElement (), seeInCurrentUrl (), seeCheckboxIsChecked (), seeInField (), seeLink (). To all these methods you can add a suffix 和 use it when you need a method that will not interrupt the test scenario when something cannot be found.
  • Cookie方法: setCookie (), grabCookie (), seeCookie ()
  • 测试场景的注释和描述: amGoingTo (), 想(), 期望(). 使用这些方法获得注释和描述良好的测试, 哪个能帮助你记住考试的目的.

因此,如果我们要测试密码重置电子邮件页面,我们可以这样做:

wantTo('Test forgotten password 功能ity');
$I->amOnPage('/forgotten')
$I->see('Enter email');
$I->fillField('email', 'incorrect@email.com”);
$I->click('Continue');
$I->expect('Reset password link not sent for incorrect email');
$I->see('Email is incorrect, try again');
$I->amGoingTo('Fill correct email 和 get link');
$I->see('Enter email');
$I->fillField('email', 'correct@email.com”);
$I->click('Continue');
$I->expect('Reset password link sent for correct email');
$I->see('Please check your email for next instructions');

It looks like this should do it, but what if there 是 some Ajax-loaded parts on the page? 我们能测试这样一个页面吗? The answer is that Codeception uses PhpBrowser, based on Symfony BrowserKit 和 Guzzle, by default. 它简单,快速,你只需要卷曲使用它.

您还可以使用Selenium并在实际浏览器中测试页面. 是的,它会慢一些,但是您也可以测试JavaScript.

首先,您需要安装Selenium驱动程序,更改验收.套件.yml并重新构建验收Tester类. 在此之后,您可以使用方法 wait ()waitForElement (). And, more interestingly, you will be able to save your time 和 resources by using methods saveSessionSnapshot ()loadSessionSnapshot (). This method allows you to store the session state 和 start new 测试 in earlier sessions. 这在某些情况下是有用的,例如,在测试授权过程中.

因此,我们最终获得了一个简单但功能强大的功能,可以测试许多函数.

功能测试

好了,是时候进行功能测试了.

$ php vendor/bin/codecept

这就是我们得到的结果:

amOnPage('/');
$I->see('Welcome');

等等,?

不,这不是错误. 功能测试应该和集成测试一样编写. The difference is that 功能 测试 是 interacting directly with your application. 这意味着您不需要web服务器来运行功能测试, 并且您有更多的能力来测试应用程序的不同部分.

它确实意味着缺乏对所有框架的支持, 但支持的框架列表很广泛:Symfony, Silex, Phalcon, Yii, Zend框架, 流明, Laravel. 对于大多数情况和大多数开发人员来说,这应该足够了. Please consult Codeception’s module documentation to get a list of available functions 和 then just switch it on in 功能.套件.yml.

Codeception supports major frameworks: Symfony, Silex, Phalcon, Yii, Zend框架, 流明, Laravel.

Codeception supports major frameworks: Symfony, Silex, Phalcon, Yii, Zend框架, 流明, Laravel.

在我们继续进行单元测试之前,请允许我讲一点题外话. 正如您可能已经注意到的,我们使用以下关键字创建了我们的测试:

$ php vendor/bin/codecept

这并不是创建测试的唯一方法. 也有 c测试. 不同之处在于你可以在一个类中构建多个相关的场景:

$ php vendor/bin/codecept
amOnPage('/forgotten')
    }

    公共函数_after(验收Tester $I)
    {
    }

    / /测试
    公共函数testEmailField(验收Tester $I)
    {
	$I->see('Enter email');

    }
    公共函数testIncorrectEmail(验收Tester $I)
    {
	$I->fillField('email', 'incorrect@email.com”);
	$I->click('Continue');
	$I->see('Email is incorrect, try again');
    }
    公共函数testCorrectEmail(验收Tester $I)
    {
	$I->fillField('email', 'correct@email.com”);
	$I->click('Continue');
	$I->see('Please check your email for next instructions');
    }
}

在本例中,方法 _before ()_after () 在每次测试之前和之后运行. 的实例 验收Tester 类被传递给每个测试,因此您可以像在测试中一样使用它. This style of 测试 can be useful in certain situations, so it is worth keeping in mind.

单元测试

是时候进行单元测试了.

Codeception是基于PHPUnit)的,所以你可以使用为PHPUnit)编写的测试. 要添加新的PHPUnit)测试,请使用以下方法:

$ php vendor/bin/codecept生成:php单位 单位 HelloWorld

或者只是继承你的测试 \ PHPUnit)_Framework_TestCase.

但如果你想要更多的东西,你应该试试Codeception的单元测试:

生成测试单元HelloWorld
setEmail('correct@email.com”);
	$user->save();
	$user = user::find(1);
	$this->assertEquals('correct@email.com', $user->getEmail());
    }
}

现在没什么不寻常的. 方法 _before ()_after ()设置()tearDown () 类似并将在每次测试之前和之后运行.

The main advantage of this test is in its ability to extend your testing process by including modules that can be switched on in 单位.套件.yml:

  • Access to memcache 和 databases to track changes (MySQL, SQLite, PostgreSQL, MongoDB 是 supported)
  • REST/SOAP应用程序的测试
  • 队列

每个模块都有自己的特点, so it is best to check the documentation 和 collect the necessary information for each module before proceeding to actual 测试.

另外,您可以使用Codeception/Specify包(需要添加到 作曲家.json),并写如下描述:

user = User::find(1);
   }
    testUserEmailSave()
    {
	$this->specify("email can be stored", function() {
            	$this->user->setEmail('correct@email.com”);
		$this->user->save();
		$user = user::find(1);
            	$this->assertEquals('correct@email.com', $user->getEmail());
        	});
    }
}

这些闭包函数中的PHP代码是隔离的, 因此,内部的更改不会影响到其他代码. Descriptions will help you to make the test more readable 和 make it easier to identify failed 测试.

作为可选的附加选项,您可以使用package Codeception \验证 类似bdd的语法:

getEmail())->equals('correct@email.com”);
}

当然你也可以用存根:

 'correct@email.com ']);
        $this->assertEquals('correct@email.com', $user->getEmail());
}

结论:共同欺骗节省了时间和精力

那么你对Codeception有什么期待呢? 是给谁的?? 有什么需要注意的吗?

Codeception can be employed by developers with vastly different PHP profficiency levels 和 teams of all sizes.

Codeception can be employed by developers with vastly different PHP profficiency levels 和 teams of all sizes.

在我看来, this testing framework is suitable for all sorts of different teams: Large 和 small, 初学者和 久经沙场的PHP专家, those who 是 using a popular framework, 和 those who 是n’t using any framework.

无论如何,这一切都归结为: Codeception即将迎来黄金时期.

It is a mature 和 well-documented framework that may easily be extended by numerous modules. 共同欺骗是现代的, 而是基于久经考验的PHPUnit), 这应该让那些不想做太多实验的开发者放心.

It performs well, which means it’s fast 和 doesn’t require too much time 和 effort. 更好的是, 它相对容易掌握, 丰富的文档应该有助于轻松的学习过程.

Codeception is also easy to install 和 configure, yet it boasts a lot of advanced options. 虽然大多数用户不需要所有的(或确实, 他们中的大多数, 这完全取决于你打算用它做什么. You can start with the basics, 和 the extra features will come in h和y sooner or later.

聘请Toptal这方面的专家.
现在雇佣
瓦西里•Koval

瓦西里•Koval

验证专家 在工程
20 的经验

基辅,乌克兰

2015年11月15日成为会员

作者简介

Vasily is a web developer with more than nine years of extensive experience developing, 优化, 支持web应用程序.

阅读更多
authors 是 vetted experts in their fields 和 write on topics in which they have demonstrated experience. All of our content is peer reviewed 和 validated by Toptal experts in the same field.

专业知识

世界级的文章,每周发一次.

订阅意味着同意我们的 隐私政策

世界级的文章,每周发一次.

订阅意味着同意我们的 隐私政策

Toptal开发者

加入总冠军® 社区.