如何在 cucumber cli 之外定义和调用 cucumber steps/scenarios?
How can I define and call cucumber steps/scenarios outside of the cucumber cli?
我有一个工作的黄瓜设置。我的 features/
文件夹有功能和步骤定义,我可以在命令行调用 cucumber
到 运行 测试套件。
我还有一个单独的脚本,我想启用它来调用一些黄瓜测试。我知道在黄瓜步骤定义中,可以从另一个步骤调用一个步骤。但我不知道如何:
- 需要我的功能文件
- 需要我的步骤文件
- 和 运行 feature/scenario/steps 的一些系列。
从 relishApp cucumber api docs,我收集了这个:
require 'cucumber'
# run all features
runtime = Cucumber::Runtime.new
Cucumber::Cli::Main.new([]).execute!(runtime)
这将 运行 我所有的黄瓜测试,就像我从命令行 运行 cucumber
一样,包括格式。但是,我不确定如何使用这种方法来:
- 运行 特定功能或步骤
- 继续脚本的其余部分(因为
execute!
退出程序)。
我也一直在查看黄瓜源代码以尝试 write/invoke 动态步骤:
require 'cucumber'
Given(/foo/) {}
# this raises an error:
# NoMethodError: undefined method `register_rb_step_definition'
# for Cucumber::RbSupport::RbLanguage:Class
# from /usr/local/lib/ruby/gems/2.0.0/gems/cucumber/2.4.0/lib
# /cucumber/rb_support/rb_dsl.rb:28
# :in `register_rb_step_definition
# A way to make `'register_rb_step_definition'` succeed:
runtime = Cucumber::Runtime.new
config = Cucumber::Configuration.new
language = Cucumber::RbSupport::RbLanguage.new(runtime, config)
dsl = Cucumber::RbSupport::RbDsl
dsl.rb_language = language
steps = {}
steps["foo"] = dsl.register_rb_step_definiton(/foo (.+)/, ->(args) { puts args })
# Now I have a 'steps' hash like {"foo" => foo_step_object}
# I can call a step like so:
steps["foo"].invoke(["bar"]) # the argument to invoke is an array or hash
# this will print bar to the console like the step proc instructed
这成功地定义和调用了测试,但是有一些缺点:
- 有必要将步骤名称和参数分开。理想情况下,我希望能够调用
step("foo bar")
而不是编写 steps["foo"].invoke(["bar"])
。在我当前尝试调用步骤时,定义中的正则表达式被忽略了。
- 如果使用 CLI 输出格式化程序就好了。
我一直在查看有关 Cucumber 的一些讨论,似乎有人在推动删除使用 steps
方法调用步骤的功能。换句话说,所有的步骤嵌套都应该通过将代码重构为单独的方法来完成,而不是通过引用其他步骤来完成。我理解这个概念的灵感,但我仍然设想一个用例:
- 在全局范围内定义正则表达式匹配器
- 提供一个字符串,找到正则表达式匹配,然后执行步骤
- 对输出使用格式化程序
如果使用 cucumber
shell 命令 运行,这基本上就是 Cucumber 的工作方式,尽管它要求所有步骤都在功能和场景中 运行 .如果我的应用只需要'steps',但是需要定义一个全局的'feature'和'scenario',那就这样吧,但我还是想只用Ruby,不转到 cucumber
shell 命令。
你想要的是
require 'cucumber'
require 'path_to_step_defs.rb'
这样做是加载文件 path_to_step_defs.rb
一次,而且只加载一次。那你就不需要load_step_definitions
这个方法了,因为脚本文件已经加载了它需要的
这是对我有用的示例,手动定义和调用步骤:
require 'cucumber' # must require everything; otherwise Configuration cannot be initialized
config = Cucumber::Configuration.new
dsl = Object.new.extend(Cucumber::RbSupport::RbDsl)
rb_language = Cucumber::RbSupport::RbLanguage.new(:unused, config)
step_search = Cucumber::StepMatchSearch.new(rb_language.method(:step_matches), config)
dsl.Given(/hello (.*)/) { |foo| puts "argument given was: #{foo}" }
match = step_search.call('hello world').first
match.step_definition.invoke(match.args) # => argument given was: world
它也会为冗余或不明确的步骤定义引发异常:
dsl.Given(/hello (.*)/) { }
dsl.Given(/(.*) world/) { }
step_search.call('hello world')
# => Cucumber::Ambiguous: Ambiguous match of "hello world"
如果您还打算拥有实际的功能文件或步骤定义文件,但不希望将它们包括在内,请记住在没有任何参数的情况下初始化 Configuration
将自动加载一些文件夹:
config = Cucumber::Configuration.new
config.autoload_code_paths
# => ["features/support", "features/step_definitions"]
config = Cucumber::Configuration.new(autoload_code_paths: [])
config.autoload_code_paths
# => []
我有一个工作的黄瓜设置。我的 features/
文件夹有功能和步骤定义,我可以在命令行调用 cucumber
到 运行 测试套件。
我还有一个单独的脚本,我想启用它来调用一些黄瓜测试。我知道在黄瓜步骤定义中,可以从另一个步骤调用一个步骤。但我不知道如何:
- 需要我的功能文件
- 需要我的步骤文件
- 和 运行 feature/scenario/steps 的一些系列。
从 relishApp cucumber api docs,我收集了这个:
require 'cucumber'
# run all features
runtime = Cucumber::Runtime.new
Cucumber::Cli::Main.new([]).execute!(runtime)
这将 运行 我所有的黄瓜测试,就像我从命令行 运行 cucumber
一样,包括格式。但是,我不确定如何使用这种方法来:
- 运行 特定功能或步骤
- 继续脚本的其余部分(因为
execute!
退出程序)。
我也一直在查看黄瓜源代码以尝试 write/invoke 动态步骤:
require 'cucumber'
Given(/foo/) {}
# this raises an error:
# NoMethodError: undefined method `register_rb_step_definition'
# for Cucumber::RbSupport::RbLanguage:Class
# from /usr/local/lib/ruby/gems/2.0.0/gems/cucumber/2.4.0/lib
# /cucumber/rb_support/rb_dsl.rb:28
# :in `register_rb_step_definition
# A way to make `'register_rb_step_definition'` succeed:
runtime = Cucumber::Runtime.new
config = Cucumber::Configuration.new
language = Cucumber::RbSupport::RbLanguage.new(runtime, config)
dsl = Cucumber::RbSupport::RbDsl
dsl.rb_language = language
steps = {}
steps["foo"] = dsl.register_rb_step_definiton(/foo (.+)/, ->(args) { puts args })
# Now I have a 'steps' hash like {"foo" => foo_step_object}
# I can call a step like so:
steps["foo"].invoke(["bar"]) # the argument to invoke is an array or hash
# this will print bar to the console like the step proc instructed
这成功地定义和调用了测试,但是有一些缺点:
- 有必要将步骤名称和参数分开。理想情况下,我希望能够调用
step("foo bar")
而不是编写steps["foo"].invoke(["bar"])
。在我当前尝试调用步骤时,定义中的正则表达式被忽略了。 - 如果使用 CLI 输出格式化程序就好了。
我一直在查看有关 Cucumber 的一些讨论,似乎有人在推动删除使用 steps
方法调用步骤的功能。换句话说,所有的步骤嵌套都应该通过将代码重构为单独的方法来完成,而不是通过引用其他步骤来完成。我理解这个概念的灵感,但我仍然设想一个用例:
- 在全局范围内定义正则表达式匹配器
- 提供一个字符串,找到正则表达式匹配,然后执行步骤
- 对输出使用格式化程序
如果使用 cucumber
shell 命令 运行,这基本上就是 Cucumber 的工作方式,尽管它要求所有步骤都在功能和场景中 运行 .如果我的应用只需要'steps',但是需要定义一个全局的'feature'和'scenario',那就这样吧,但我还是想只用Ruby,不转到 cucumber
shell 命令。
你想要的是
require 'cucumber'
require 'path_to_step_defs.rb'
这样做是加载文件 path_to_step_defs.rb
一次,而且只加载一次。那你就不需要load_step_definitions
这个方法了,因为脚本文件已经加载了它需要的
这是对我有用的示例,手动定义和调用步骤:
require 'cucumber' # must require everything; otherwise Configuration cannot be initialized
config = Cucumber::Configuration.new
dsl = Object.new.extend(Cucumber::RbSupport::RbDsl)
rb_language = Cucumber::RbSupport::RbLanguage.new(:unused, config)
step_search = Cucumber::StepMatchSearch.new(rb_language.method(:step_matches), config)
dsl.Given(/hello (.*)/) { |foo| puts "argument given was: #{foo}" }
match = step_search.call('hello world').first
match.step_definition.invoke(match.args) # => argument given was: world
它也会为冗余或不明确的步骤定义引发异常:
dsl.Given(/hello (.*)/) { }
dsl.Given(/(.*) world/) { }
step_search.call('hello world')
# => Cucumber::Ambiguous: Ambiguous match of "hello world"
如果您还打算拥有实际的功能文件或步骤定义文件,但不希望将它们包括在内,请记住在没有任何参数的情况下初始化 Configuration
将自动加载一些文件夹:
config = Cucumber::Configuration.new
config.autoload_code_paths
# => ["features/support", "features/step_definitions"]
config = Cucumber::Configuration.new(autoload_code_paths: [])
config.autoload_code_paths
# => []