天9:功能测试
昨天,我们看到了如何使用石灰Jobeet类的单元测试测试库打包symfony。ob娱乐下载今天,我们将编写功能测试的功能我们已经实现工作
和类别
模块。
功能测试
功能测试是一个伟大的工具,从端到端测试应用程序:从请求由浏览器发送的服务器的响应。他们测试应用程序的所有层:路由模型,行动,和模板。他们非常类似于你可能已经做的手工:每次添加或修改一个动作,你需要走到浏览器并检查每件事都按预期工作通过点击链接和检查元素呈现的页面。换句话说,你运行一个场景用例对应您刚刚实施。
这个过程是手动,单调乏味,而且容易出错。每次你改变的东西在你的代码中,您必须遍历所有场景,以确保你没有打破的东西。这是疯狂的。功能测试在symfony提供了一种方便地ob娱乐下载描述场景。每个场景可以自动播放一遍又一遍地在浏览器中通过模拟用户的经验。单元测试一样,他们给你信心代码在和平。
请注意
功能测试框架取代工具不像”硒”。硒直接在浏览器中运行自动化测试在许多平台和浏览器,它可以测试应用程序的JavaScript。
的sfBrowser
类
在syob娱乐下载mfony,功能测试是通过一个特殊的浏览器运行,实现的sfBrowser
类。它作为一个浏览器定制为您的应用程序和直接连接,而不需要一个web服务器。它允许您访问所有symfony对象之前和之后的每一个要ob娱乐下载求,让你有机会反省,做你想做的检查编程。
sfBrowser
提供了方法,模拟导航在一个典型的浏览器:
方法 | 描述 |
---|---|
get () |
得到一个URL |
post () |
发布一个URL |
叫() |
(用于调用一个URL把 和删除 方法) |
回() |
返回上一个页面 |
转发() |
前进一页历史 |
重载() |
重新加载当前页面 |
click () |
点击一个链接或按钮 |
select () |
选择一个radiobutton或复选框 |
取消选择() |
取消选中radiobutton或复选框 |
重启() |
重新启动浏览器 |
下面是一些使用的例子sfBrowser
方法:
美元的浏览器=新sfBrowser();美元的浏览器- >得到(' / ')- >点击(“设计”)- >得到(“页面/类别/编程吗? = 2”)- >得到(“/类别/编程”,数组(“页面”= >2))- >帖子(“搜索”,数组(“关键词”= >“php”));
sfBrowser
包含额外的方法来配置浏览器行为:
方法 | 描述 |
---|---|
setHttpHeader () |
设置HTTP头 |
setAuth () |
设置基本的身份验证凭证 |
setCookie () |
设置一个饼干 |
removeCookie () |
删除一个饼干 |
clearCookies () |
清除当前所有饼干 |
followRedirect () |
遵循一个重定向 |
的sfTestFunctional
类
我们有一个浏览器,但是我们需要一种方法来反省symfony对象来进行实际的测试。ob娱乐下载这是可以做到与石灰和一些sfBrowser
方法如getResponse ()
和getRequest ()
但是syob娱乐下载mfony提供了一个更好的方法。
提供的测试方法是另一个类,sfTestFunctional
这需要一个sfBrowser
实例构造函数。的sfTestFunctional
类代表测试测试人员对象。几个测试人员与symfony绑定,您还可以创建自己的。ob娱乐下载
我们看到在第8天,功能测试存储下测试/功能/
目录中。Jobeet,测试中发现的测试/功能/前端/
子目录,每个应用程序都有自己的子目录中。这个目录已经包含两个文件:categoryActionsTest.php
,jobActionsTest.php
因为所有的任务自动生成模块创建一个基本的功能测试文件:
/ /测试/功能/前端/ categoryActionsTest.php包括(目录名(__FILE__)。“/ . . / . . /引导/ functional.php”);美元的浏览器=新sfTestFunctional(新sfBrowser());美元的浏览器- >得到(“/类别/指数”)- >与(“请求”)- >开始()- >isParameter(“模块”,“类别”)- >isParameter(“行动”,“指数”)- >结束()- >与(“响应”)- >开始()- >isStatusCode(200年)- >checkElement(“身体”,”!/这是一个临时的页面的)- >结束();
乍一看,上面的脚本可能看起来有点奇怪。这是因为的方法sfBrowser
和sfTestFunctional
实现一个连贯接口由总是返回这个美元
。它允许您链方法要求更好的可读性。上面的代码片段相当于:
/ /测试/功能/前端/ categoryActionsTest.php包括(目录名(__FILE__)。“/ . . / . . /引导/ functional.php”);美元的浏览器=新sfTestFunctional(新sfBrowser());美元的浏览器- >得到(“/类别/指数”);美元的浏览器- >与(“请求”)- >开始();美元的浏览器- >isParameter(“模块”,“类别”);美元的浏览器- >isParameter(“行动”,“指数”);美元的浏览器- >结束();美元的浏览器- >与(“响应”)- >开始();美元的浏览器- >isStatusCode(200年);美元的浏览器- >checkElement(“身体”,”!/这是一个临时的页面的);美元的浏览器- >结束();
测试是在一个测试块上下文中运行。始于一个测试块上下文(测试人员名字)- >开始()
和结尾结束()
:
美元的浏览器- >与(“请求”)- >开始()- >isParameter(“模块”,“类别”)- >isParameter(“行动”,“指数”)- >结束();
代码测试请求参数模块
=类别
和行动
=指数
。
提示
当你只需要调用一个测试方法在一个测试人员,你不需要创建一个块:(“请求”)- > isParameter(“模块”,“类别”)
。
要求测试人员
的要求测试人员反省和测试提供了测试方法sfWebRequest
对象:
方法 | 描述 |
---|---|
isParameter () |
检查一个请求参数的值 |
isFormat () |
检查请求的格式 |
isMethod () |
检查的方法 |
hasCookie () |
检查请求是否有饼干的 |
名字 | |
isCookie () |
检查一个cookie的值 |
响应测试仪
还有一个响应测试仪类,它提供了对测试的方法sfWebResponse
对象:
方法 | 描述 |
---|---|
checkElement () |
检查是否响应匹配标准的CSS选择器 |
checkForm () |
检查一个sfForm 表单对象 |
调试() |
输出响应输出,以减轻调试 |
匹配() |
测试响应与regexp |
isHeader () |
检查一个头的值 |
isStatusCode () |
检查响应状态码 |
isRedirected () |
检查当前的反应是一个重定向 |
isValid () |
检查是否格式良好的XML响应(你也再次验证响应文档类型被传递真正的 作为参数) |
请注意
我们将在未来几天内描述多个测试类(形式、用户缓存,…)。
运行功能测试
对于单元测试,发射功能测试可以通过直接执行测试文件:
php测试/功能/前端/ categoryActionsTest.php美元
或通过使用功能测试:
任务:
美元php ob娱乐下载symfony测试:功能前端categoryActions
测试数据
至于推动单元测试,我们需要加载每次我们推出一个功能测试的测试数据。我们可以重用我们之前写过的代码:
包括(目录名(__FILE__)。“/ . . / . . /引导/ functional.php”);美元的浏览器=新sfTestFunctional(新sfBrowser());美元的装载机=新sfPropelData();美元的装载机- >loadData(sfConfig::得到(“sf_test_dir”)。/设备的);
加载数据功能测试在单元测试中有点容易引导已经初始化数据库的脚本。
对于单元测试,我们不会复制和粘贴这段代码在每个测试文件,但我们将创建自己的功能的类继承自sfTestFunctional
:
/ / lib /测试/ JobeetTestFunctional.class.php类JobeetTestFunctional扩展sfTestFunctional{公共函数loadData(){美元的装载机=新sfPropelData();美元的装载机- >loadData(sfConfig::得到(“sf_test_dir”)。/设备的);返回这个美元;}}
编写功能测试
编写功能测试在浏览器就像玩一个场景。我们已经写了所有的场景,我们需要测试的第二天的故事。
首先,让我们测试Jobeet主页通过编辑jobActionsTest.php
测试文件。用以下代码替换代码:
过期的职位没有列出
/ /测试/功能/前端/ jobActionsTest.php包括(目录名(__FILE__)。“/ . . / . . /引导/ functional.php”);美元的浏览器=新JobeetTestFunctional(新sfBrowser());美元的浏览器- >loadData();美元的浏览器- >信息(“1 -主页”)- >得到(' / ')- >与(“请求”)- >开始()- >isParameter(“模块”,“工作”)- >isParameter(“行动”,“指数”)- >结束()- >与(“响应”)- >开始()- >信息(“1.1 -过期未列出的工作”)- >checkElement(”。乔布斯td.position:包含(“过期”),假)- >结束();
与石灰
,可以通过调用插入一个信息性消息信息()
方法使输出更加可读。核实过期的排除工作的主页,我们检查的CSS选择器指导td.position:包含(“过期”)
不匹配的任何地方响应的HTML内容(请记住,在夹具文件,唯一过期的工作我们有包含“过期”的位置)。当第二个参数checkElement ()
方法是一个布尔值,该方法测试节点相匹配的CSS选择器的存在。
提示
的checkElement ()
方法是能够解释最有效的CSS3选择器。
只有n工作类别列出
添加以下代码的测试文件:
/ /测试/功能/前端/ jobActionsTest.php美元最大= sfConfig::得到(“app_max_jobs_on_homepage”);美元的浏览器- >信息(“1 -主页”)- >得到(' / ')- >信息(sprintf(“1.2——只有% s工作列出一个类别的,美元最大))- >与(“响应”)- >checkElement(”。category_programming tr的,美元最大);
的checkElement ()
方法还可以检查一个CSS选择器匹配“n”文档中的节点通过一个整数作为第二个参数。
一个类别有一个链接到目录页只有太多的工作
/ /测试/功能/前端/ jobActionsTest.php美元的浏览器- >信息(“1 -主页”)- >得到(' / ')- >信息(“1.3 -一个类别有一个链接到目录页只有太多的乔布斯)- >与(“响应”)- >开始()- >checkElement(”。category_design .more_jobs”,假)- >checkElement(”。category_programming .more_jobs”)- >结束();
在这些测试中,我们检查没有“更多就业机会”链接设计类别(.category_design .more_jobs
不存在),有一个“工作岗位”链接的编程类(.category_programming .more_jobs
确实存在)。
工作是按日期排序
/ /最近在编程工作类别美元标准=新标准();美元标准- >添加(JobeetCategoryPeer::鼻涕虫,“编程”);美元的类别= JobeetCategoryPeer::doSelectOne(美元标准);美元标准=新标准();美元标准- >添加(JobeetJobPeer::EXPIRES_AT,时间()标准::GREATER_THAN);美元标准- >添加(JobeetJobPeer::CATEGORY_ID添加,美元的类别- >getId());美元标准- >addDescendingOrderByColumn(JobeetJobPeer::CREATED_AT);美元的工作= JobeetJobPeer::doSelectOne(美元标准);美元的浏览器- >信息(“1 -主页”)- >得到(' / ')- >信息(1.4 -工作是按日期排序的)- >与(“响应”)- >开始()- >checkElement(sprintf(”。category_programming tr:第一(href * = " / % d /”)”,美元的工作- >getId()))- >结束();
测试工作实际上是按日期排序,我们需要检查在主页上列出的第一份工作是我们期待的。这可以通过检查URL包含预期的主键。之间的主键可以改变,我们需要先将对象从数据库中。
即使测试工作,我们需要重构代码,得到第一份工作的编程类可以重用在其他地方在我们的测试中。我们不会将代码移动到模型层测试特定的代码。相反,我们将代码JobeetTestFunctional
我们之前已经创建了类。这个类作为一个领域特定functional tester Jobeet类:
/ / lib /测试/ JobeetTestFunctional.class.php类JobeetTestFunctional扩展sfTestFunctional{公共函数getMostRecentProgrammingJob(){/ /最近在编程工作类别美元标准=新标准();美元标准- >添加(JobeetCategoryPeer::鼻涕虫,“编程”);美元的类别= JobeetCategoryPeer::doSelectOne(美元标准);美元标准=新标准();美元标准- >添加(JobeetJobPeer::EXPIRES_AT,时间()标准::GREATER_THAN);美元标准- >添加(JobeetJobPeer::CATEGORY_ID添加,美元的类别- >getId());美元标准- >addDescendingOrderByColumn(JobeetJobPeer::CREATED_AT);返回JobeetJobPeer::doSelectOne(美元标准);}/ /……}
你现在可以取代先前的测试代码如下:
/ /测试/功能/前端/ jobActionsTest.php美元的浏览器- >信息(“1 -主页”)- >得到(' / ')- >信息(1.4 -工作是按日期排序的)- >与(“响应”)- >开始()- >checkElement(sprintf(”。category_programming tr:第一(href * = " / % d /”)”,美元的浏览器- >getMostRecentProgrammingJob()- >getId()))- >结束();
每个工作在主页上点击
美元的工作=美元的浏览器- >getMostRecentProgrammingJob();美元的浏览器- >信息(“2 -工作页面”)- >得到(' / ')- >信息(“2.1——每个工作在主页上点击并给出详细的信息)- >点击(Web开发人员的,数组(),数组(“位置”= >1))- >与(“请求”)- >开始()- >isParameter(“模块”,“工作”)- >isParameter(“行动”,“显示”)- >isParameter(“company_slug”,美元的工作- >getCompanySlug())- >isParameter(“location_slug”,美元的工作- >getLocationSlug())- >isParameter(“position_slug”,美元的工作- >getPositionSlug())- >isParameter(“id”,美元的工作- >getId())- >结束();
要测试主页上的链接工作,我们模拟一个点击“Web开发人员”文本。在页面上有很多人,我们有明确要求浏览器单击第一个(数组(“位置”= > 1)
)。
每个请求参数然后测试确保路由正确地做了它的工作。
学习的例子
在本节中,我们提供了所需的所有代码测试工作和类别页。仔细阅读代码,你可以学习一些新的整洁的技巧:
/ / lib /测试/ JobeetTestFunctional.class.php类JobeetTestFunctional扩展sfTestFunctional{公共函数loadData(){美元的装载机=新sfPropelData();美元的装载机- >loadData(sfConfig::得到(“sf_test_dir”)。/设备的);返回这个美元;}公共函数getMostRecentProgrammingJob(){/ /最近在编程工作类别美元标准=新标准();美元标准- >添加(JobeetCategoryPeer::鼻涕虫,“编程”);美元的类别= JobeetCategoryPeer::doSelectOne(美元标准);美元标准=新标准();美元标准- >添加(JobeetJobPeer::EXPIRES_AT,时间()标准::GREATER_THAN);美元标准- >addDescendingOrderByColumn(JobeetJobPeer::CREATED_AT);返回JobeetJobPeer::doSelectOne(美元标准);}公共函数getExpiredJob(){/ /过期的工作美元标准=新标准();美元标准- >添加(JobeetJobPeer::EXPIRES_AT,时间()标准::LESS_THAN);返回JobeetJobPeer::doSelectOne(美元标准);}}/ /测试/功能/前端/ jobActionsTest.php包括(目录名(__FILE__)。“/ . . / . . /引导/ functional.php”);美元的浏览器=新JobeetTestFunctional(新sfBrowser());美元的浏览器- >loadData();美元的浏览器- >信息(“1 -主页”)- >得到(' / ')- >与(“请求”)- >开始()- >isParameter(“模块”,“工作”)- >isParameter(“行动”,“指数”)- >结束()- >与(“响应”)- >开始()- >信息(“1.1 -过期未列出的工作”)- >checkElement(”。乔布斯td.position:包含(“过期”),假)- >结束();美元最大= sfConfig::得到(“app_max_jobs_on_homepage”);美元的浏览器- >信息(“1 -主页”)- >信息(sprintf(“1.2——只有% s工作列出一个类别的,美元最大))- >与(“响应”)- >checkElement(”。category_programming tr的,美元最大);美元的浏览器- >信息(“1 -主页”)- >得到(' / ')- >信息(“1.3 -一个类别有一个链接到目录页只有太多的乔布斯)- >与(“响应”)- >开始()- >checkElement(”。category_design .more_jobs”,假)- >checkElement(”。category_programming .more_jobs”)- >结束();美元的浏览器- >信息(“1 -主页”)- >信息(1.4 -工作是按日期排序的)- >与(“响应”)- >开始()- >checkElement(sprintf(”。category_programming tr:第一(href * = " / % d /”)”,美元的浏览器- >getMostRecentProgrammingJob()- >getId()))- >结束();美元的工作=美元的浏览器- >getMostRecentProgrammingJob();美元的浏览器- >信息(“2 -工作页面”)- >得到(' / ')- >信息(“2.1——每个工作在主页上点击并给出详细的信息)- >点击(Web开发人员的,数组(),数组(“位置”= >1))- >与(“请求”)- >开始()- >isParameter(“模块”,“工作”)- >isParameter(“行动”,“显示”)- >isParameter(“company_slug”,美元的工作- >getCompanySlug())- >isParameter(“location_slug”,美元的工作- >getLocationSlug())- >isParameter(“position_slug”,美元的工作- >getPositionSlug())- >isParameter(“id”,美元的工作- >getId())- >结束()- >信息(2.2 -一个不存在的工作将用户转发到404)- >得到(' /工作/ foo-inc / milano-italy / 0 /画家”)- >与(“响应”)- >isStatusCode(404年)- >信息(2.3 -一个过期的工作页面转发用户404的)- >得到(sprintf(' /工作/ sensio-labs /法国巴黎/ % d / web开发人员的,美元的浏览器- >getExpiredJob()- >getId()))- >与(“响应”)- >isStatusCode(404年);/ /测试/功能/前端/ categoryActionsTest.php包括(目录名(__FILE__)。“/ . . / . . /引导/ functional.php”);美元的浏览器=新JobeetTestFunctional(新sfBrowser());美元的浏览器- >loadData();美元的浏览器- >信息(“1 -类别页面”)- >信息(在主页上的1.1 -类别可点击的)- >得到(' / ')- >点击(“编程”)- >与(“请求”)- >开始()- >isParameter(“模块”,“类别”)- >isParameter(“行动”,“显示”)- >isParameter(“鼻涕虫”,“编程”)- >结束()- >信息(sprintf(“1.2 -类别有超过% s工作也有一个“更多”链接的,sfConfig::得到(“app_max_jobs_on_homepage”)))- >得到(' / ')- >点击(“27岁”)- >与(“请求”)- >开始()- >isParameter(“模块”,“类别”)- >isParameter(“行动”,“显示”)- >isParameter(“鼻涕虫”,“编程”)- >结束()- >信息(sprintf(1.3——只有%年代乔布斯列出,sfConfig::得到(“app_max_jobs_on_category”)))- >与(“响应”)- >checkElement(”。乔布斯tr的,sfConfig::得到(“app_max_jobs_on_category”))- >信息(“1.4 -是分页列出的工作”)- >与(“响应”)- >开始()- >checkElement(“.pagination_desc”,/ 32工作的)- >checkElement(“.pagination_desc”,“# 1/2页#”)- >结束()- >点击(' 2 ')- >与(“请求”)- >开始()- >isParameter(“页面”,2)- >结束()- >与(“响应”)- >checkElement(“.pagination_desc”,“#页面2/2 #”);
调试功能测试
有时一个功能测试失败。因为sob娱乐下载ymfony模拟浏览器没有任何图形界面,很难诊断问题。谢天谢地,symfonyob娱乐下载提供了~ |调试调试~ ()
方法输出响应头和内容:
美元的浏览器- >与(“响应”)- >调试();
的调试()
方法可以插入任何地方响应
测试块并将停止脚本执行。
功能测试工具
的功能测试:
任务也可以用于启动应用程序的所有功能测试:
美元php ob娱乐下载symfony测试:功能的前端
任务为每个测试文件输出一行:
测试工具
正如您可能期望的那样,还有一个任务启动项目的所有测试(单元测试和功能):
php syob娱乐下载mfony测试:美元
当你有一个大型的测试套件,它可以是非常耗时间的发射所有测试每次你做出改变,特别是一些测试失败。这是因为每次你解决一个测试,你应该再次运行整个测试套件,以确保你没有打破东西。但只要失败的测试都不是固定不变的,是没有意义的重新执行所有其他测试。的测试:所有
有一个任务——only-failed
选项,部队的任务只有在上一次运行重新执行测试失败:
php syob娱乐下载mfony测试:美元——only-failed
你第一次运行的任务,像往常一样运行所有测试。但对于后续的测试运行,仅执行上次测试失败。当你修复你的代码,会通过一些测试,并将在随后的运行中删除。当所有测试通过,完整的测试套件运行……然后您可以清洗和重复的方法。
提示
如果你想测试套件集成在一个持续集成过程中,使用——xml
选项强迫测试:所有
任务生成JUnit兼容的XML输出。
美元php ob娱乐下载symfony测试:所有——xml = log.xml
最终的想法
以上就是我们旅游symfony的测试工具。ob娱乐下载你没有理由再也不测试您的应用程序!石灰框架和功能测试框架,symfony提供了强大的工具来帮助你编写测试。ob娱乐下载
我们刚刚触及表面的功能测试。从现在开始,每次我们实现一个功能,我们还将学习更多的功能编写测试的测试框架。
明天,我们将谈论symfony的另一大特性:ob娱乐下载形式的框架。
这项工作在Creative Commons许可Attribution-Share都3.0 Unported许可执照。