11天:测试表单
在第十天,我们用symfony创建我们的第一个形式。ob娱乐下载人们现在能够在Jobeet发布一份新工作,但我们用光了时间我们可以添加一些测试。这就是我们会沿着这些线路。在这个过程中,我们还将学习更多关于形式框架。
侧边栏
使用表单框架没有symfonyob娱乐下载
symfob娱乐下载ony框架组件是完全解耦。这意味着可以使用他们中的大多数不使用整个MVC框架。是这样的形式框架,它没有依赖symfony。ob娱乐下载你可以用它在任何PHP应用程序的lib /形式/
,lib / widget /
,lib /验证/
目录。
另一个可重用的组件是路由框架。复制lib /路由
在non-symfony项目目录,受益于免费ob娱乐下载漂亮的url。
symfony独立的组件组成ob娱乐下载ob娱乐下载symfony的平台:
提交表单
让我们打开jobActionsTest
文件为创造就业添加功能测试和验证过程。
在文件的末尾添加以下代码来得到这份工作创建页面:
/ /测试/功能/前端/ jobActionsTest.php美元的浏览器- >信息(“3 -提交一份工作页面”)- >信息(3.1 -提交作业的)- >得到(' /工作/新')- >与(“请求”)- >开始()- >isParameter(“模块”,“工作”)- >isParameter(“行动”,“新”)- >结束();
我们已经使用了click ()
方法来模拟点击链接。相同的click ()
方法可用于提交表单。对于一个表单,您可以通过提交每个字段的值作为该方法的第二个参数。像一个真正的浏览器,浏览器对象将合并表单的提交值的默认值。
但通过字段值,我们需要知道他们的名字。如果你开放源代码或使用Firefox的Web开发人员工具栏“形式>显示表单详细信息”功能,您将看到的名称公司
字段是jobeet_job[公司]
。
请注意
当PHP遇到一个输入字段的名称jobeet_job[公司]
,它会自动将其转换为一个数组的名字jobeet_job
。
让事情看起来更干净,让我们改变格式工作(% s)
通过添加以下代码结束的时候配置()
的方法JobeetJobForm
:
/ / lib /形式/ JobeetJobForm.class.php这个美元- >widgetSchema- >setNameFormat(“工作(% s)”);
这种变化后,公司
名字应该是工作(公司)
在您的浏览器中。现在可以点击“预览你的工作”按钮,将有效的值传递给形式:
/ /测试/功能/前端/ jobActionsTest.php美元的浏览器- >信息(“3 -提交一份工作页面”)- >信息(3.1 -提交作业的)- >得到(' /工作/新')- >与(“请求”)- >开始()- >isParameter(“模块”,“工作”)- >isParameter(“行动”,“新”)- >结束()- >点击(预览你的工作的,数组(“工作”= >数组(“公司”= >“Sensio赞助实验室”,“url”= >“http://www.sensio.com/”,“标志”= > sfConfig::得到(“sf_upload_dir”)。“/工作/ sensio-labs.gif”,“位置”= >“开发人员”,“位置”= >美国亚特兰大的,“描述”= >“你将与symfony开发网站为我们的客ob娱乐下载户。,“how_to_apply”= >给我发邮件的,“电子邮件”= >“for.a.job@example.com”,“is_public”= >假,)))- >与(“请求”)- >开始()- >isParameter(“模块”,“工作”)- >isParameter(“行动”,“创建”)- >结束();
浏览器也模拟文件上传,如果你通过绝对路径文件上传。
提交表单后,我们检查的操作执行创建
。
测试形式
我们有提交应该有效。你可以通过测试形式测试器:
与(“形式”)- >开始()- >hasErrors(假)- >结束()- >
形式测试人员有几个方法来测试当前的形式状态,这样的错误。
如果你犯了一个错误在测试,测试不通过,您可以使用(响应)- > ~ |调试调试~ ()
声明我们已经看到在白天9。但是你必须深入生成的HTML检查错误消息。那不是很方便。测试人员还提供了一个形式调试()
方法,输出表单状态和所有与之相关的错误消息:
与(“形式”)- >调试()
重定向测试
形式是有效的,工作应该是创建和用户重定向到显示
页面:
与(“响应”)- >isRedirected()- >followRedirect()- >与(“请求”)- >开始()- >isParameter(“模块”,“工作”)- >isParameter(“行动”,“显示”)- >结束()- >
的isRedirected ()
如果页面重定向和测试followRedirect ()
遵循重定向的方法。
请注意
浏览器类不会自动重定向您可能想要反省之前重定向对象。
推动测试人员
最后,我们想要测试工作已经在数据库中创建和检查is_activated
列被设置为假
当用户尚未发表。
可以很容易地通过使用另一个测试人员,推动测试器。作为推动测试不是默认注册,现在让我们将它添加:
美元的浏览器- >的地上(“推动”,“sfTesterPropel”);
推动测试人员提供check ()
方法来检查一个或多个对象在数据库中匹配的标准作为参数传递。
与(“推动”)- >开始()- >检查(“JobeetJob”,数组(“位置”= >美国亚特兰大的,“is_activated”= >假,“is_public”= >假,))- >结束()
标准可以像上面的数组值,或标准
对于更复杂的查询实例。您可以测试对象匹配标准的存在与一个布尔第三个参数(默认真正的
),或者匹配对象的数量通过一个整数。
测试错误
按预期工作表单创建工作当我们提交有效值。让我们添加一个测试来检查的行为,当我们提交无效的数据:
美元的浏览器- >信息(与无效值的3.2 -提交作业)- >得到(' /工作/新')- >点击(预览你的工作的,数组(“工作”= >数组(“公司”= >“Sensio赞助实验室”,“位置”= >“开发人员”,“位置”= >美国亚特兰大的,“电子邮件”= >“not.an.email”,)))- >与(“形式”)- >开始()- >hasErrors(3)- >返回错误(“描述”,“要求”)- >返回错误(“how_to_apply”,“要求”)- >返回错误(“电子邮件”,“无效”)- >结束();
的hasErrors ()
方法可以测试的数量错误如果通过一个整数。的返回错误()
方法测试错误代码对于一个给定的字段。
提示
在测试我们有书面提交无效的数据,我们没有测试整个表单。我们只有添加测试特定的东西。
你也可以测试生成的HTML检查它包含错误消息,但没有必要在我们的例子中,我们没有定制的表单布局。
现在,我们需要测试管理酒吧的工作预览页面。当一个工作尚未激活,您可以编辑、删除、或发布工作。为了测试这三个链接,我们需要首先创建一个工作。但大量的复制和粘贴。我不喜欢浪费e-trees,让我们添加一个工作方法的创造者JobeetTestFunctional
类:
/ / lib /测试/ JobeetTestFunctional.class.php类JobeetTestFunctional扩展sfTestFunctional{公共函数createJob(美元的价值=数组()){返回这个美元- >得到(' /工作/新')- >点击(预览你的工作的,数组(“工作”= >array_merge(数组(“公司”= >“Sensio赞助实验室”,“url”= >“http://www.sensio.com/”,“位置”= >“开发人员”,“位置”= >美国亚特兰大的,“描述”= >“你将与symfony开发网站为我们的客ob娱乐下载户。,“how_to_apply”= >给我发邮件的,“电子邮件”= >“for.a.job@example.com”,“is_public”= >假,),美元的价值)))- >followRedirect();}/ /……}
的createJob ()
方法创建一个工作,遵循并返回浏览器重定向到不打破连贯接口。你还可以通过一个数组的值将与一些默认值。
迫使HTTP方法的链接
测试“发布”链接现在更简单:
美元的浏览器- >信息(“3.3 -在预览页面,您可以发布工作的)- >createJob(数组(“位置”= >“FOO1”))- >点击(“发布”,数组(),数组(“方法”= >“把”,“_with_csrf”= >真正的))- >与(“推动”)- >开始()- >检查(“JobeetJob”,数组(“位置”= >“FOO1”,“is_activated”= >真正的,))- >结束();
如果你还记得第十天,“出版”链接配置为被称为HTTP把
方法。浏览器不理解把
请求,link_to ()
助手将链接到一个表单和一些JavaScript。测试浏览器不执行JavaScript,我们需要力量的方法把
通过它的第三种选择click ()
方法。此外,link_to ()
助手也嵌入CSRF令牌在第一天我们使CSRF保护;的_with_csrf
选择模拟这个令牌。
测试“删除”链接非常相似:
美元的浏览器- >信息(“3.4 -在预览页面,您可以删除工作的)- >createJob(数组(“位置”= >“FOO2”))- >点击(“删除”,数组(),数组(“方法”= >“删除”,“_with_csrf”= >真正的))- >与(“推动”)- >开始()- >检查(“JobeetJob”,数组(“位置”= >“FOO2”,),假)- >结束();
测试作为一个保障
发表一份工作时,您不能编辑了。即使“编辑”链接不再显示在预览页面,让我们添加一些测试的需求。
首先,添加另一个参数createJob ()
方法允许自动的出版工作,并创建一个getJobByPosition ()
方法返回一个工作由于其位置的值:
/ / lib /测试/ JobeetTestFunctional.class.php类JobeetTestFunctional扩展sfTestFunctional{公共函数createJob(美元的价值=数组(),美元发布=假){这个美元- >得到(' /工作/新')- >点击(预览你的工作的,数组(“工作”= >array_merge(数组(“公司”= >“Sensio赞助实验室”,“url”= >“http://www.sensio.com/”,“位置”= >“开发人员”,“位置”= >美国亚特兰大的,“描述”= >“你将与symfony开发网站为我们的客ob娱乐下载户。,“how_to_apply”= >给我发邮件的,“电子邮件”= >“for.a.job@example.com”,“is_public”= >假,),美元的价值)))- >followRedirect();如果(美元发布){这个美元- >点击(“发布”,数组(),数组(“方法”= >“把”,“_with_csrf”= >真正的))- >followRedirect();}返回这个美元;}公共函数getJobByPosition(美元的地位){美元标准=新标准();美元标准- >添加(JobeetJobPeer::位置,美元的地位);返回JobeetJobPeer::doSelectOne(美元标准);}/ /……}
如果工作是出版,编辑页面必须返回404状态码:
美元的浏览器- >信息(“3.5 -发表一份工作时,它不能被编辑了”)- >createJob(数组(“位置”= >“FOO3”),真正的)- >得到(sprintf(/工作/ %年代/编辑,美元的浏览器- >getJobByPosition(“FOO3”)- >getToken()))- >与(“响应”)- >开始()- >isStatusCode(404年)- >结束();
但是如果你运行测试,你不会有预期的结果正如我们昨天忘了实现这个安全措施。编写测试也是一个伟大的方式来发现错误,你需要考虑所有的边界情况。
修复bug非常简单,我们只需要404页如果工作被激活:
/ /应用程序/前端/模块/工作/行动/ actions.class.php公共函数executeEdit(sfWebRequest美元的请求){美元的工作=这个美元- >getRoute()- >getObject();这个美元- >forward404If(美元的工作- >getIsActivated());这个美元- >形式=新JobeetJobForm(美元的工作);}
修复是微不足道的,但你确定一切还像预期的那样工作吗?您可以打开您的浏览器并开始测试所有可能的组合来访问编辑页面。但是有一种更简单的方法:运行测试套件;如果你有了回归,symfony会告诉你。ob娱乐下载
回到未来的测试
当一个工作是在不到五天,到期或如果它已经过期,用户可以扩展工作验证另一个30天从当前日期。
在浏览器中测试这个要求并不容易随着到期日自动设置创建工作时在未来30天。所以,当工作页面,来扩展的链接不存在的工作。当然,你可以攻击的截止日期在数据库中,或调整模板总是显示链接,但这是单调乏味,而且容易出错。您已经猜到,编写一些测试将帮助我们一次。
像往常一样,我们需要添加的新路线扩展
第一个方法:
#应用/前端/ config /路由。yml工作:类:sfPropelRouteCollection选项:模型:JobeetJob专栏:令牌object_actions:{发布:把,延长:把}要求:令牌:\ w +
然后,更新“扩展”链接代码_admin
部分:
< !- - - - - -- - - - - -apps/frontend/modules/job/templates/_admin.php -->< ? php如果(美元的工作- >expiresSoon()):? >- - - - - -< ? php回声link_to(“扩展”,“job_extend”,美元的工作,数组(“方法”= >“把”))? >为另一个< ? php回声sfConfig::得到(“app_active_days”)? >天< ? phpendif? >
然后,创建一个扩展
行动:
/ /应用程序/前端/模块/工作/行动/ actions.class.php公共函数executeExtend(sfWebRequest美元的请求){美元的请求- >checkCSRFProtection();美元的工作=这个美元- >getRoute()- >getObject();这个美元- >forward404Unless(美元的工作- >扩展());这个美元- >getUser()- >setFlash(“通知”,sprintf(你的工作有效性一直延长到% s。,美元的工作- >getExpiresAt(' m / d / Y ')));这个美元- >重定向(“job_show_user”,美元的工作);}
预期的行动,扩展()
的方法JobeetJob
返回真正的
如果被扩展或工作假
否则:
/ / lib /模型/ JobeetJob.php类JobeetJob扩展BaseJobeetJob{公共函数扩展(){如果(!这个美元- >expiresSoon()){返回假;}这个美元- >setExpiresAt(时间()+86400年* sfConfig::得到(“app_active_days”));返回这个美元- >保存();}/ /……}
最后,添加一个测试场景:
美元的浏览器- >信息(“3.6 -工作有效性不能延长工作期满之前很快的)- >createJob(数组(“位置”= >“FOO4”),真正的)- >调用(sprintf(/工作/ % s /扩展的,美元的浏览器- >getJobByPosition(“FOO4”)- >getToken()),“把”,数组(“_with_csrf”= >真正的))- >与(“响应”)- >开始()- >isStatusCode(404年)- >结束();美元的浏览器- >信息(“3.7 -工作有效性可以扩展当工作很快到期)- >createJob(数组(“位置”= >“FOO5”),真正的);美元的工作=美元的浏览器- >getJobByPosition(“FOO5”);美元的工作- >setExpiresAt(时间());美元的工作- >保存();美元的浏览器- >调用(sprintf(/工作/ % s /扩展的,美元的工作- >getToken()),“把”,数组(“_with_csrf”= >真正的))- >与(“响应”)- >isRedirected();美元的工作- >重新加载();美元的浏览器- >测试()- >是(美元的工作- >getExpiresAt(“y / m / d '),日期(“y / m / d ',时间()+86400年* sfConfig::得到(“app_active_days”)));
本测试场景介绍一些新事物:
- 的
叫()
方法检索URL的方法不同得到
或帖子
- 工作已经更新后的行动,我们需要重新加载本地对象
$工作- >重载()
- 最后,我们使用嵌入式
石灰
对象直接测试新的截止日期。
形式的安全
形式序列化魔法!
推动形式非常容易使用,因为他们很多工作自动化。例如,序列化表单数据库调用一样简单形式- > save ()
。
但它是如何工作的呢?基本上,save ()
方法遵循以下步骤:
- 开始一个事务(因为嵌套推动形式都是保存在一举)
- 提交的值(通过调用过程
updateCOLUMNColumn ()
方法如果它们存在的话) - 调用驱动对象
fromArray ()
更新的列值的方法 - 将对象保存到数据库中
- 提交事务
内置的安全功能
的fromArray ()
方法以一个数组的值和更新相应的列值。这代表着安全问题吗?如果有人试图提交一个值为一列,他没有授权?例如,我可以强迫令牌
列?
让我们写一个测试来模拟一个作业提交令牌
字段:
/ /测试/功能/前端/ jobActionsTest.php美元的浏览器- >得到(' /工作/新')- >点击(预览你的工作的,数组(“工作”= >数组(“令牌”= >“fake_token”,)))- >与(“形式”)- >开始()- >hasErrors(7)- >hasGlobalError(“extra_fields”)- >结束();
当提交表单时,你必须有一个extra_fields
全球的错误。这是因为默认形式不允许额外的字段在提交的值。这也是为什么所有的表单字段必须有一个相关的验证器。
提示
你也可以提交附加字段从舒适的浏览器工具栏使用Firefox的Web开发人员等工具。
你可以绕过这个安全措施通过设置allow_extra_fields
选项真正的
:
类MyForm扩展sfForm{公共函数配置(){/ /……这个美元- >validatorSchema- >setOption(“allow_extra_fields”,真正的);}}
现在必须通过测试,但是令牌
价值已被过滤掉的价值观。所以,你仍然无法绕过安全措施。但如果你真的想要的值,设置filter_extra_fields
选项假
:
这个美元- >validatorSchema- >setOption(“filter_extra_fields”,假);
请注意
测试写在本节只用于演示目的。现在您可以删除它们从Jobeet项目测试不需要验证symfony的特性。ob娱乐下载
XSS和CSRF保护
在第一天,你学会了生成:应用程序
默认任务创建一个安全的应用程序。
首先,它使对XSS的保护。这意味着所有变量中使用默认模板是逃脱了。如果你想提交一份工作描述与一些HTML标签在里面,你会注意到当symfony呈现工作页面,描述的HTML标记不解释,但显示为纯文本。ob娱乐下载
然后,它使CSRF保护。CSRF标记时,所有形式嵌入_csrf_token
隐藏字段。
提示
逃避策略和CSRF秘密可以改变在任何时候通过编辑应用程序/前端/ config / settings.yml
配置文件。至于databases.yml
文件,设置可由环境配置:
:.settings: #形式安全秘密(CSRF保护)csrf_secret:独特ecret #输出美元逃离设置escaping_strategy:真正的escaping_method: ESC_SPECIALCHARS
维护任务
即使symfonob娱乐下载y是一个web框架,它有一个命令行工具。你已经使用它来创建默认的项目和应用程序的目录结构,但也为模型生成各种文件。添加一个新的任务非常容易使用的工具的symfony命令行被打包在一个框架。ob娱乐下载
当用户创建一个工作,他必须把它在线激活它。但如果不是,数据库将增长与陈旧的工作。让我们创建一个任务,从数据库中删除过时的工作。这个任务必须定期运行cron作业。
/ / lib /任务/ JobeetCleanupTask.class.php类JobeetCleanupTask扩展sfBaseTask{受保护的函数配置(){这个美元- >使用addoption(数组(新sfCommandOption(“env”,零,sfCommandOption::PARAMETER_REQUIRED,“复现的环境”,“刺激”),新sfCommandOption(“天”,零,sfCommandOption::PARAMETER_REQUIRED,”,90年),));这个美元- >名称空间=“jobeet”;这个美元- >的名字=“清理”;这个美元- >briefDescription=“清理Jobeet数据库”;这个美元- >detailedDescription= < < < EOF的(jobeet:清理|信息]任务清理Jobeet数据库:(。/ob娱乐下载 symfony jobeet:清理——env = =刺激——天90年|信息]EOF;}受保护的函数执行(美元的参数=数组(),选择美元=数组()){databaseManager美元=新sfDatabaseManager(这个美元- >配置);nb美元= JobeetJobPeer::清理(选择美元(“天”]);这个美元- >logSection(“推动”,sprintf('删除% d陈旧的乔布斯,nb美元));}}
在任务配置配置()
方法。每个任务必须有一个唯一的名称(名称空间
:的名字
),可以有参数和选项。
提示
浏览内置symfony任务(ob娱乐下载lib /任务/
)使用的例子。
的jobeet:清理
任务定义了两个选择:- - - env
和——天
用一些合理的缺省值。
运行任务类似于任何其他运行symfony内置的任务:ob娱乐下载
php syob娱乐下载mfony jobeet:美元清理-天= 10 - env = dev
像往常一样,数据库清理代码已被提出的JobeetJobPeer
类:
/ / lib /模型/ JobeetJobPeer.php静态公共函数清理(美元的天){美元标准=新标准();美元标准- >添加(自我::IS_ACTIVATED,假);美元标准- >添加(自我::CREATED_AT,时间()- - - - - -86400年*美元的天标准::LESS_THAN);返回自我::doDelete(美元标准);}
的doDelete ()
删除数据库记录匹配给定的方法标准
对象。它还可以将一个主键数组。
请注意
symfob娱乐下载ony任务的行为和他们的环境很好地返回一个值根据任务的成功。你可以强迫一个返回值,返回一个整数明确的任务。
最终的想法
测试是在symfony的核心理念和工具。ob娱乐下载今天,我们又学会了如何利用symfony工具使开发过程更容易,更快,更重要的是,更安全。ob娱乐下载
不仅仅sob娱乐下载ymfony的形式框架提供了小部件和验证器:它能给你一个简单的方法来测试您的表单和确保您的默认形式是安全的。
我们的旅游symfony的特性并没有ob娱乐下载在这里结束。明天,我们将创建Jobeet的后端应用程序。创建一个后端接口是必须的对于大多数web项目,和Jobeet也不例外。但是我们如何能够开发这样一个接口在短短一个小时吗?简单,我们将使用symfony管理发电机框架。ob娱乐下载
这项工作在Creative Commons许可Attribution-Share都3.0 Unported许可执照。