Cucumber 经验总结

来源:互联网 发布:算法结构 编辑:程序博客网 时间:2024/05/17 23:45

背景

使用一段时间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.featurepost_add.featurepost_delete_when_no_permission.feature

Steps 不要overload web_steps

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

可按功能拆分steps:

user_stepspost_stepsblog_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.rbcomment_steps.rb       lightbox_steps.rb      posts_steps.rb         template_steps.rbconversations_steps.rb mention_steps.rb       profile_steps.rb       uri-step.rbcustom_web_steps.rb    message_steps.rb       scope_steps.rb         user_steps.rbdebug_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_loginend
  3. features/support/user_cuke_helpers.rb

    # use the @me user to perform a manual login via the sign_in pagedef 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_filesdragon.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 stepsFactoryGirl.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.flushallend

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

  • http://www.elabs.se/blog/15-you-re-cuking-it-wrong
  • http://eggsonbread.com/2010/09/06/my-cucumber-best-practices-and-tips/
  • http://benmabey.com/2008/05/19/imperative-vs-declarative-scenarios-in-user-stories.html
  • Rspec specification

  • http://spin.atomicobject.com/2011/06/02/never-say-click-good-cucumber-system-testing-practices/

  • http://www.cowboycoded.com/2011/01/05/better-web-steps-for-cucumber-with-capybara/

  • https://github.com/thoughtbot/capybara-webkit/wiki/Installing-Qt-and-compiling-capybara-webkit

  • http://robots.thoughtbot.com/post/189412598/five-ridiculously-awesome-cucumber-and-webrat

  • http://collectiveidea.com/blog/archives/2011/05/25/testing-with-sunspot-and-cucumber/

  • http://www.cowboycoded.com/2011/01/05/better-web-steps-for-cucumber-with-capybara/

  • http://blog.trydionel.com/2010/02/06/testing-sunspot-with-cucumber/

0 0