使用Cucumber+Rspec玩转BDD(5)——安全退出
使用Cucumber+Rspec玩转BDD(5)——安全退出
2009年3月20日 星期五
### 温故知新 ###
为了保护用户的隐私,限制特定资料的访问,前面我们给系统增加了登录功能;紧接着,又为了方便用户在一段时间之内不必重复登录操作,我们实现了用户的持久登录状态,即“记住我”功能。如果浏览器未关闭,或者用户一直处于在线状态,而用户自己并没有使用这台设备,很显然,这对用户的帐号是非常危险的;基于此,系统应该提供一个给用户手工注销在线状态退出站点的功能。
为了获得更好的阅读体验,读者朋友们可以在这里下载源码:http://github.com/404/bdd_user_demo/tree/master
### 新建工作分支 ###
$ git checkout -b user_logout
### 用户注销退出功能 ###
1.提供一个“退出”链接,用户登录后点击该链接可以注销在线状态;
2.用户登录并勾选记住我后,点击“退出”链接可以注销在线状态,下次访问的时候将不再自动登录。
下面来编写对应于以上功能的故事场景。
### 故事用例之用户注销退出 ###
$ gedit features/user_logout.feature
功能: 用户安全退出
为了保护我的帐号不被他人非法使用
作为一名已经登录的在线用户
我希望能够安全退出
场景: 用户注销在线状态
假如 我已经使用<404/xuliicom@gmail.com/password>注册过且已经激活了帐号
当 我以<xuliicom@gmail.com/password>这个身份登录
那么 我应该成功登录网站
当 我退出网站
那么 我应该看到<您已经安全退出>的提示信息
而且 我应该尚未登录
场景: 用户在持久在线状态下退出
假如 我已经使用<404/xuliicom@gmail.com/password>注册过且已经激活了帐号
当 我以<xuliicom@gmail.com/password>这个身份登录并勾选<记住我>
那么 我应该成功登录网站
当 我退出网站
那么 我应该看到<您已经安全退出>的提示信息
而且 我应该尚未登录
当 我关闭网页下次再来访问的时候
那么 我应该尚未登录
可以把一个feature文件当作一份书面需求的电子版,如果你觉得文件开头几句没什么用(为了...作为...我希望...),那直接在那里罗列出功能简要咯,故事场景就当作详尽的需求来写。例如:
功能: 用户安全退出
1.提供一个“退出”链接,用户登录后点击该链接可以注销在线状态;
2.用户登录并勾选记住我后,点击“退出”链接可以注销在线状态,下次访问的时候将不再自动登录。
场景1
...
场景2
...
若真那样,说不定可以节约不少会议时间,因为用于测试的故事文本(feature文件)完全可以替代现实中的功能需求书,而且更加灵活。再向前一步,就可以直接把客户说的需求整理到测试中去,完了发动测试引擎一直在那转动着,开发人员和测试引擎凑到一块儿玩结对编程……敏捷开发,我们还需要文档么?
回头干正事儿,保存 user_logout.feature。运行测试看看它能告诉我们应该做些什么,
$ ruby script/cucumber -l zh-CN features/user_logout.feature
### 编写测试脚本 ###
如上图所示,我们需要为“当 我退出网站”定义所需的运行脚本。
$ gedit features/step_definitions/user_steps.rb
# user logout
When /^我退出网站$/ do
visit '/logout', :delete
end
保存user_steps.rb。运行测试,
$ ruby script/cucumber -l zh-CN features/user_logout.feature
### 配置登出路由(logout_path) ###
没有找到"/logout"这一访问路径,因为我们还没有在 routes.rb 配置文件中定义"/logout"。修改 routes.rb 文件,添加这条路由信息,
$ gedit config/routes.rb
为了sessions资源看起来有紧凑的结构,我们稍微变换了login_path的定义,与logout_path整合到了一起。
map.with_options :controller => 'sessions' do |page|
page.login '/login', :action => 'new'
page.logout '/logout', :action => 'destroy'
end
### 实现用户注销退出 ###
既然 "/logout" 路由指向了 SessionsController 类的 destroy 方法,那么我们还需要编写 destroy 方法的具体实现。
$ gedit app/controllers/sessions_controller.rb
添加 destroy 方法,
def destroy
forget(current_user)
reset_session
flash[:notice] = "您已经安全退出!"
redirect_to login_path
end
在 private 之后添加 forget 方法,
def forget(user)
user.forget_me! if user
cookies.delete :remember_token
end
### 删除服务端的remember_token ###
在forget方法中,程序调用了User实例对象的forget_me!方法;然后清除了当前客户端与服务端会话的cookies;仅仅清除客户端的cookies还不够,服务器上的也应该一并删除。
$ gedit app/models/user.rb
添加forget_me!方法,
# 删除数据库里边的remember_token
def forget_me!
self.remember_token_expires_at = nil
self.remember_token = nil
save(false)
end
保存 user.rb。运行测试,
$ ruby script/cucumber -l zh-CN features/user_logout.feature
测试通过!
### 亲临现场 ###
为了方便登录用户能够以鼠标点击的方式退出站点,也为了方便开发人员自己手工测试,此时还需要给登录用户提供一个用于注销退出的链接。在之前设置的访问控制中,用户资料显示页面只能在用户登录以后才可见,我们可以将此退出链接加到这个页面中。
$ gedit app/views/users/show.html.erb
在该模板文件末尾加上如下一段代码,
<p>
<%= link_to "安全退出", logout_path %>
</p>
保存 show.html.erb。打开 Web Server 手工测试看看,
$ ruby script/server
打开浏览器,登录到用户资料查看页面;
点击“安全退出”链接,我们看到系统将我们带到了用户登录页面;
再次刷新刚才那个用户资料显示页面,系统给我们呈现的是一张登录表单;事实说明我们已经成功登出了。
### 下节预告 ###
接下来的一章里,我们将会回到发送邮件的操作上,与之前发送激活邮件不同的是,下一次将会给忘记密码的用户发送一封用于找回密码的邮件。所以,我们下一章的主题就是找回密码。
### 提交工作成果到GIT仓库 ###
$ git status
$ git add .
$ git commit -m "A user can be logout."
$ git checkout master
$ git merge user_logout
$ git branch -d user_logout
$ git tag v5
(注意,真正的开发中可不是到功能开发完毕了才commit,而是边开发边add和commit。为了方便演示编码过程,文章中没有一一列举。)
作者:
fandyst
出处: http://www.cnblogs.com/todototry/
关注语言: python、javascript(node.js)、objective-C、java、R、C++
兴趣点: 互联网、大数据技术、大数据IO瓶颈、col-oriented DB、Key-Value DB、数据挖掘、模式识别、deep learning、开发与成本管理
产品:
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
出处: http://www.cnblogs.com/todototry/
关注语言: python、javascript(node.js)、objective-C、java、R、C++
兴趣点: 互联网、大数据技术、大数据IO瓶颈、col-oriented DB、Key-Value DB、数据挖掘、模式识别、deep learning、开发与成本管理
产品:
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。