Cucumber 经验总结

背景

使用一段时间cucumber了,也看过一些书 The cucumber book, rspec book, 翻过一些github上开源项目的cucumber,再结合自己项目和团队项目的经验做个总结

Process 流程

是否采用

不是必须,看实际情况。我个人是非常推荐使用。总要考虑几个问题

  • 投入成本,包括编写,和维护(保持更新),运行时间
  • 效果,是否需要持续集成

好处

  • 当要deploy前,绿色一大片的感觉让你觉得更有安全感。
  • 自动化测试,减少大量的从复劳动
  • 代码变更时,自动化测试可追踪代码变更是否对现有功能有所影响

谁来编写

是否由测试人员撰写,我个人是推荐由开发人员编写,但每个feature的定义和Scenario由产品经理/测试人员是定义。

Case 1测试人员编写

  • 没再为功能性测试编写Test case
  • 不能快速完成,因为steps需要了解背后实现(理论上不需要,但很多exceptional case)
  • 需要开发人员支持,讲述给测试人员,一些steps的trick way

Case 2开发人员编写

  • 估算时带来好处,不需要为测试人员等待开发人员完成代码的时间作估算
  • 开发人员一般都不喜欢写测试用例,强制要求,也只能写出基本流程的测试(总比没有强)

结论

  • 开发人员写cucumber,代码重用性和质量会高很多,效率也高
  • 测试人员定制scenario,和定义测试用例test case的道理一样,会全面很多

其它可能性

可以采取由开发人员轮流坐庄写cucumber,不过这个我没机会实践,所以不知道效果会如何。

采用BDD?

写rspec时,好流行安装guard,然后代码改变时,同时运行相应的rspec,理论上cucumber也可以这样做,我反对这样做。

主要是cucumber运行的实在太慢,会严重打击你的积极性。另外,spork和guard spork也是默认不对代码修改,运行cucumber,这也是有道理的。

代码

Naming convention 文件命名规范

一般采用,对像加行为的描述,也用附加特定条件或范围的。也可以将行为放在前面。

[module]_[action]_[prep]_[condition].feature

Example:

user_signin_through_oauth_sina.feature

post_add.feature

post_delete_when_no_permission.feature

Steps 不要overload web_steps

不要直接添加在 web_steps.rb 和 support/env.rb了,非常快就overload失控 实际上 web_steps 已经不再默认生成。

可按功能拆分steps:

user_steps post_steps blog_steps

是否使用Background

分两种观点,一种利用background ,可以抽取公用到background 一种是不写background,每个scenario 独立

这里没有定论,我编向是写background,简单来讲,就是可重复使用前提条件,不好的地方就是降低可阅读性。但维护时会减轻工作量。如果不是为了生成的cucumber文档给产品经理看,我觉得还是使用background比较好。

DRY 原则 (imperative or declarative)

将相同步骤cucumber 变成一个step,即复用你的cucumber steps 网上有大量的讨论,关于使用哪个好,我个人偏好是imperative,原因是,大量的declarative steps会造成维护困难,改起来非常累

可以看看这两篇

cucumber-imperative-or-declarative-that-is-the-question/

Imperative vs declarative scenarios in user story

Cucumber steps基本规范

Cucumber的steps尽量用人类看得懂的语言,所有 正则表达式,css, xpath,等各种代码不应该在cucumber steps中出现。需要时,就另外写一个steps封装一下就好。

文件目录结构,附开源项目的做法

可以将按模块划分,将相应的features放入子目录,如果features少,也可以省略。但不要用sprint11, 或milestone11这种目录,一定要的话,可以写在 tag 上,如s@sprint11,否则维护起来就杯具了。

是否按标准的User story写背景和description

一种写法是 As xxx Role, I would do yyy so that zzz 这种写法会对项目新成员会有一定的帮助,不好的地方就是维护成本了,所以那几个开源项目都没有严格按照User story的写法,只是简单完成即可。我偏向是简单写,直观明了。

diaspora

命名规范 [action]_[item].feature 没有子目录

    accepts_invitation.feature         edits_profile.feature              oembed.feature
    activity_stream.feature            follows_tags.feature               photo_lightbox.feature
    aspect_navigation.feature          invitations.feature                posts_from_main_page.feature
    blocks_user.feature                logged_out_browsing.feature        reshare.feature
    change_email.feature               logs_in_and_out.feature            show_more.feature
    change_password.feature            manages_aspects.feature            signs_up.feature
    closes_account.feature             mentions.feature                   step_definitions
    comments.feature                   mentions_from_profile_page.feature stops_following_users.feature
    connects_users.feature             mobile.feature                     support
    conversations.feature              not_safe_for_work.feature          tags.feature
    download_photos.feature            notifications.feature              tags_and_comments.feature
Step

大体都差不多和teambox一样, [module]_sptes.rb

aspects_steps.rb       factory_steps.rb       oembed.rb              stream_steps.rb
comment_steps.rb       lightbox_steps.rb      posts_steps.rb         template_steps.rb
conversations_steps.rb mention_steps.rb       profile_steps.rb       uri-step.rb
custom_web_steps.rb    message_steps.rb       scope_steps.rb         user_steps.rb
debug_steps.rb         mobile_steps.rb        session_steps.rb       web_steps.rb
teambox

[item]_[action].feature 我偏向这种,因为分类清楚点

    project_archive.feature              upload_rename.feature
    project_create.feature               user_change_password.feature
    project_delete.feature               user_edit_profile.feature
    project_invitations.feature          user_edit_settings.feature
    project_join.feature                 user_first_steps.feature
    project_leave.feature                user_login.feature
    project_public.feature               user_logout.feature
    public_downloads.feature             user_profile.feature
    search_projects.feature              user_reset_password.feature
    sidebar.feature                      user_signup.feature
Step
    action_steps.rb             organization_steps.rb       task_list_steps.rb
    activity_steps.rb           page_steps.rb               task_list_template_steps.rb
    authentication_steps.rb     pickle_steps.rb             task_reminders_steps.rb
    comment_steps.rb            project_steps.rb            task_steps.rb
    conversation_steps.rb       public_downloads_steps.rb   teamboxdata_steps.rb
    db_steps.rb                 relative_time_steps.rb      time_steps.rb
    email_steps.rb              reset_password_steps.rb     upload_steps.rb
    folder_steps.rb             search_steps.rb             user_steps.rb
    invitation_steps.rb         see_within_steps.rb         watchers_steps.rb
    oauth_steps.rb              sidebar_steps.rb            web_steps.rb

Cucumber样例

diaspora
  1. features/activity_stream.feature

    Feature: The activity stream
      Scenario: Sorting
        Given a user with username "bob" #没有使用pickle
        When I try to sign in manually" #一起来看看sign in吧
    
  2. features/step_definitions/session_steps.rb

    When /^I try to sign in manually$/ do
      manual_login
    end
    
  3. features/support/user_cuke_helpers.rb

    # use the @me user to perform a manual login via the sign_in page
    def manual_login
        visit login_page 
        login_as @me.username, @me.password #login_as 其实就是wrap了 fill_in 方法
    end
    
  4. features/support/paths.rb

      def login_page
        path_to "the new user session page"
      end
    
      def path_to(page_name)
        when /^the ([\w ]+) page$/
        send("#{$1.gsub(/\W+/, '_')}_path")
    

Cucumber 的测试附件存放位置

不要再使用app/assets下的东西了。

➜  sample_files git:(dev) 
ls /Users/mafai/Projects/teambox/features/support/sample_files
dragon.jpg tiger.jpg

其它工具,cucumber好帮手

Capybara

这个应该是默认的了,The cucumber book中,提及到为什么不用webrat和selenium,在这里就不废话了。

Pickle

这个gem帮你省确了大量的module创建的steps,用上好,你的steps会减少好多,但同时,你的cucumber 描述就变得不是那么容易阅读。 !注意,开源项目引入了这个gem,但并不使用它,如果你想你的cucumber steps变得更简洁和易于阅读,pickle不是你工具。

Factory girl

用上factory girl建立对像时,可以设定默认值或指定规则的value,也可以省下不少代码

Pickle.configure do |config|
  #config.adapters = [:machinist]
  config.adapters = [:factory_girl] #以后通过factory girl 来创建对像
  #config.map 'I', 'myself', 'me', 'my', :to => 'user: "me"'
end

#所有的module都须要在FactoryGirl登记一下,否则在运行时,pickle会有问题, undefined steps
FactoryGirl.define do
      factory :post do
        title { "Dummy title" }
        body  { "#{title}!" }
      end
    end

Spork

spork cucumber Spork 可以先preload 整个测试环境

cucumber -r features features/posts.feature --drb 然后就享受一下速度吧,但注意这样做好,如果你将代码修改后,其实spork不会懂得reload的。

Guard spork

guard init spork

生成

/Users/mafai/Projects/compass/Guardfile

你会发觉,即使代码出错,也不会影响cucumber的测试,主要是默认缓存了class的原因

config.cache_classes = false #改成false就好了

你也可以选择 watch 所有的*.rb文件,restart spork server,不过这实践不是这些工具所提倡的。

http://stackoverflow.com/questions/5855587/spork-is-really-great-but-how-can-i-get-it-to-refresh-validations-and-other-cod

使用webkit代替selenium

使用 webkit做前端测试,速度会提升,因为不需要打开browser,只要在env.rb用上Capybara.javascript_driver = :webkit

Trick

默认路径 path

如果是一些标准命名的page,再不须添加 path了,否则真的很烦

  else
     begin
       page_name =~ /the (.*) page/
       path_components = $1.split(/\s+/) 
       self.send(path_components.push('path').join('_').to_sym) #这个send 方法我不清楚是调用哪一个,其实就是将 user profile page,转换成 user_profile_path ,这将其转成symbol字符串 
     rescue Object => e
       raise "Can't find mapping from \"#{page_name}\" to a path.\n" +
         "Now, go and add a mapping in #{__FILE__}"
     end

运行单个cucumber

cucumber features/billing/credit_card.feature:104 -f progress -r features

Cucumber rerun 重复运行出错的scenario

$ cucumber -f rerun --out rerun.txt

#结果
features/one.feature:367 features/another.feature:91:117

启动时清数据

改一下 hook.rb就好

``` Before do $redis.flushall end

After do $redis.flushall # clean out the Solr index after each scenario Sunspot.remove_all! end ```

Devise登录

见到一种较特别的写法,就是在测试环境时,动态添加一个route和action,具体看diaspora项目的代码。其它都是模似用户的steps做的。

其它Topic,但不在此讨论

多台机器分布式运行cucumber,提速

分别打开IE, FireFox, Opera, Chrome等浏览器跑界面,进行对layout的快速review

结合bamboo server做持续集成测试

Reference

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值