Cucumber动态加载数据表

发布于 2024-12-27 03:22:36 字数 1244 浏览 2 评论 0原文

我目前正在尝试将黄瓜与水豚一起使用来进行网络应用程序的一些集成测试。

有一个测试,我只想单击 Web 应用程序的所有(或大部分)页面,看看是否没有返回错误。我希望事后能够看到哪些页面无法正常工作。

我认为场景大纲是最好的方法,所以我就这样开始:

Scenario Outline: Checking all pages pages

   When I go on the page <page>
   Then the page has no HTTP error response

    Examples:
      | page                        |
      | "/resource1"                |
      | "/resource2"                |
      ...

我目前有 82 页,效果很好。

但是我发现这种方法不可维护,因为可能会有新资源和将被删除的资源。

更好的方法是从某处加载表中的数据(解析索引页的 HTML、数据库等...)。

但我不知道该怎么做。

我遇到了一篇关于表转换的文章,但我无法弄清楚如何在场景大纲中使用此转换。

有什么建议吗?

好的,因为有一些混乱。如果你看一下上面的例子。我想做的就是更改它,使表几乎为空:

Scenario Outline: Checking all pages pages

  When I go on the page <page>
  Then the page has no HTTP error response

  Examples:
    | page                        |
    | "will be generated"         |

然后我想添加一个看起来像这样的转换:

Transform /^table:page$/ do
  all_my_pages.each do |page|
    table.hashes << {:page => page}
  end 
  table.hashes
end

我在同一个文件中指定了转换,但它没有执行,所以我假设转换不适用于场景大纲。

I am currently trying to use cucumber together with capybara for some integration tests of a web-app.

There is one test where I just want to click through all (or most of) the pages of the web app and see if no error is returned. I want to be able to see afterwards which pages are not working.

I think that Scenario outlines would be the best approach so I started in that way:

Scenario Outline: Checking all pages pages

   When I go on the page <page>
   Then the page has no HTTP error response

    Examples:
      | page                        |
      | "/resource1"                |
      | "/resource2"                |
      ...

I currently have 82 pages and that works fine.

However I find this approach is not maintable as there may new resources and resources that will be deleted.

A better approach would be to load the data from the table from somewhere (parsing HTML of an index page, the database etc...).

But I did not figure out how to do that.

I came across an article about table transformation but I could not figure out how to use this transformation in an scenario outline.

Are there any suggestions?

OK since there is some confusion. If you have a look at the example above. All I want to do is change it so that the table is almost empty:

Scenario Outline: Checking all pages pages

  When I go on the page <page>
  Then the page has no HTTP error response

  Examples:
    | page                        |
    | "will be generated"         |

Then I want to add a transformation that looks something like this:

Transform /^table:page$/ do
  all_my_pages.each do |page|
    table.hashes << {:page => page}
  end 
  table.hashes
end

I specified the transformation in the same file, but it is not executed, so I was assuming that the transformations don't work with Scenario outlines.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

樱娆 2025-01-03 03:22:36

Cucumber 对于该任务来说确实是错误的工具,您应该用特性来描述功能。如果您想以编程方式描述行为,您应该使用 rspec 或 test-unit 之类的东西。

此外,您的场景步骤应该像书面文本一样具有描述性和专业性,而不是像编程语言中使用的抽象短语。它们不应包含“附带详细信息”,例如资源的确切 url 或其 ID。

请阅读 http:// blog.carbon Five.com/2011/11/07/modern-cucumber-and-rails-no-more-training-wheels/ 并观看 http://skillsmatter.com/podcast/home/refuctoring-your-cukes

关于您的关于“插入表”的问题,是的,如果你
意味着向其中添加额外的行,事实上您可以用它做任何您喜欢的事情。
转换块的结果完全替换原始表。

Transform /^table:Name,Posts$/ do
  # transform the table into a list of hashes
  results = table.hashes.map do |row|
    user = User.create! :name => row["Name"]
    posts = (1..row["Posts"]).map { |i| Post.create! :title => "Nr #{i}" }
    { :user => user, :posts => posts }
  end
  # append another hash to the results (e.g. a User "Tim" with 2 Posts)
  tim = User.create! :name => "Tim"
  tims_posts = [Post.create! :title => "First", Post.create! :title => "Second"]
  results << { :user => tim, :posts => tims_posts }
  results
end

Given /^I have Posts of the following Users:$/ do |transformation_results|
  transformation_results.each do |row|
    # assing Posts to the corresponding User
    row[:user].posts = row[:posts]
  end
end

您可以将其与这样的场景大纲结合起来:

Scenario Outline: Paginate the post list of an user at 10
  Given I have Posts of the following Users:
    | Name | Posts |
    | Max  | 7     |
    | Tom  | 11    |
  When I visit the post list of <name>
  Then I should see <count> posts
Examples:
  | name | count |
  | Max  |     7 |
  | Tom  |    10 |
  | Tim  |     2 |

这应该说明为什么向表中“添加”行可能不是最佳实践。

请注意,不可能在表内扩展示例标签:

Scenario Outline: Paginate the post list of an user at 10
  Given I have Posts of the following Users:
    | Name   | Posts      |
    | <name> | <existing> | # won't work
  When I visit the post list of <name>
  Then I should see <displayed> posts
Examples:
  | name | existing | displayed |
  | Max  |     7    |         7 |
  | Tom  |    11    |        10 |
  | Tim  |     2    |         2 |

Cucumber is really the wrong tool for that task, you should describe functionality in terms of features. If you want to describe behavior programmatically you should use something like rspec or test-unit.

Also your scenario steps should be descriptive and specialized like a written text and not abstract phrases like used in a programming language. They should not include "incidental details" like the exact url of a ressource or it's id.

Please read http://blog.carbonfive.com/2011/11/07/modern-cucumber-and-rails-no-more-training-wheels/ and watch http://skillsmatter.com/podcast/home/refuctoring-your-cukes

Concerning your question about "inserting into tables", yes it is possible if you
mean adding additional rows to it, infact you could do anything you like with it.
The result of the Transform block completely replaces the original table.

Transform /^table:Name,Posts$/ do
  # transform the table into a list of hashes
  results = table.hashes.map do |row|
    user = User.create! :name => row["Name"]
    posts = (1..row["Posts"]).map { |i| Post.create! :title => "Nr #{i}" }
    { :user => user, :posts => posts }
  end
  # append another hash to the results (e.g. a User "Tim" with 2 Posts)
  tim = User.create! :name => "Tim"
  tims_posts = [Post.create! :title => "First", Post.create! :title => "Second"]
  results << { :user => tim, :posts => tims_posts }
  results
end

Given /^I have Posts of the following Users:$/ do |transformation_results|
  transformation_results.each do |row|
    # assing Posts to the corresponding User
    row[:user].posts = row[:posts]
  end
end

You could combine this with Scenario Outlines like this:

Scenario Outline: Paginate the post list of an user at 10
  Given I have Posts of the following Users:
    | Name | Posts |
    | Max  | 7     |
    | Tom  | 11    |
  When I visit the post list of <name>
  Then I should see <count> posts
Examples:
  | name | count |
  | Max  |     7 |
  | Tom  |    10 |
  | Tim  |     2 |

This should demonstarte why "adding" rows to a table, might not be best practice.

Please note that it is impossible to expand example tags inside of a table:

Scenario Outline: Paginate the post list of an user at 10
  Given I have Posts of the following Users:
    | Name   | Posts      |
    | <name> | <existing> | # won't work
  When I visit the post list of <name>
  Then I should see <displayed> posts
Examples:
  | name | existing | displayed |
  | Max  |     7    |         7 |
  | Tom  |    11    |        10 |
  | Tim  |     2    |         2 |
揪着可爱 2025-01-03 03:22:36

对于动态加载数据的具体情况,这里有一个建议:

  1. 一个类,比如说 PageSets,其中包含一些方法,例如 all_pages_in_the_sitemap_errorcountdeveloping_countries_errorcount >.

  2. 类似于的步骤

    鉴于我位于“检查内容”页面
    然后“发展中国家”页面有 0 个错误
    

or

    Then there are 0 errors in "all pages in the sitemap"

的步骤Then 步骤将字符串 "developmenting states" 转换为方法名称 developmenting_countries_errorcount并尝试在PageSets类上调用它。在这种情况下,该步骤期望所有 _errorcount 方法返回一个整数。返回诸如映射之类的数据结构为您提供了编写简洁动态步骤的多种可能性。

对于更多静态数据,我们发现 YAML 非常有用,可以让我们的测试自记录和自验证,并帮助我们删除难以维护的文字,例如“5382739”,三周后我们都忘记了它们的含义。

YAML 格式易于阅读,并且可以在必要时进行注释(通常不是。)

而不是编写:

Given I am logged in as "[email protected]"
And I select the "History" tab
Then I can see 5 or more "rows of history"

我们可以改为编写:

Given I am logged in as "a user with at least 5 items of history"
When I select the "History" tab
Then I can see 5 or more "rows of history"

在文件logins.yaml....

a member with at least 5 items of history:
     username: [email protected]
     password: WalRus

我们使用 YAML 来保存与所有内容相关的数据集各种实体,如成员、提供者、策略……该列表一直在增长:

在文件 test_data.yaml 中……

a member who has direct debit set up:
    username: [email protected]
    password: WalRus
    policyId: 5382739
    first name: Jack
    last name: Robinson
    partner's first name: Sally
    partner's last name: Fredericks

还值得查看 YAML 的 多行文本工具(如果需要)来验证文本。尽管这对于自动化测试来说并不常见,但有时很有用。

For the specific case of loading data dynamically, here's a suggestion:

  1. A class, let's say PageSets, with methods, e.g. all_pages_in_the_sitemap_errorcount, developing_countries_errorcount.

  2. a step that reads something like

    Given I am on the "Check Stuff" page
    Then there are 0 errors in the "developing countries" pages
    

or

    Then there are 0 errors in "all pages in the sitemap"

The Then step converts the string "developing countries" into a method name developing_countries_errorcountand attempts to call it on class PageSets. The step expects all _errorcount methods to return an integer in this case. Returning data structures like maps gives you many possibilities for writing succinct dynamic steps.

For more static data we have found YAML very useful for making our tests self-documenting and self-validating, and for helping us remove hard-to-maintain literals like "5382739" that we've all forgotten the meaning of three weeks later.

The YAML format is easy to read and can be commented if necessary (it usually isn't.)

Rather than write:

Given I am logged in as "[email protected]"
And I select the "History" tab
Then I can see 5 or more "rows of history"

We can write instead:

Given I am logged in as "a user with at least 5 items of history"
When I select the "History" tab
Then I can see 5 or more "rows of history"

In file logins.yaml....

a member with at least 5 items of history:
     username: [email protected]
     password: WalRus

We use YAML to hold sets of data relating to all sorts of entities like members, providers, policies, ... the list is growing all the time:

In file test_data.yaml...

a member who has direct debit set up:
    username: [email protected]
    password: WalRus
    policyId: 5382739
    first name: Jack
    last name: Robinson
    partner's first name: Sally
    partner's last name: Fredericks

It's also worth looking at YAML's multi-line text facilities if you need to verify text. Although that's not usual for automation tests, it can sometimes be useful.

清泪尽 2025-01-03 03:22:36

我认为更好的方法是使用不同的工具,仅用于抓取您的网站并检查是否没有返回错误。假设您正在使用 Rails

您可能考虑的工具是:Tarantula

https://github.com/relevance/tarantula

我希望有所帮助:)

I think that the better approach would be using different tool, just for crawling your site and checking if no error is returned. Assuming you're using Rails

The tool you might consider is: Tarantula.

https://github.com/relevance/tarantula

I hope that helps :)

黑色毁心梦 2025-01-03 03:22:36

一个快速的方法是更改​​示例收集器代码,并使用 ruby​​ 的 eval 运行自定义的 ruby​​ 函数来覆盖默认收集的示例数据,代码如下:
生成动态示例-for-cucumber

缺点:需要更改scenario_outline.rb文件。

A quick hack is to change the Examples collector code, and using eval of ruby to run your customized ruby function to overwrite the default collected examples data, here is the code:
generate-dynamic-examples-for-cucumber

drawback: need change the scenario_outline.rb file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文