我打算创建一个基于Cucumber场景生成应用程序代码的插件,但我想确保我不会在这里重新发明轮子。是否有人知道一个与Cucumber一起使用并生成模型,控制器和视图的插件?
关于我想要做的事情的一点背景,以防这没有意义。当我在这里创建一个新的应用程序时,我的工作流程是:
在我的白板上绘制出两种类型的高级设计。 1显示模型和关系,另一个显示布局,表单等的原始屏幕
根据高级设计编写黄瓜场景(但更细粒度)。其中许多步骤仅描述了我将在特定视图中看到的内容,并概述了应用程序的流程。我发现在开始编码之前创建我能想到的所有场景比在编写每个场景后一次完成一个并编码更好。
我运行黄瓜场景并查看第一次失败并从那里开始编码。在此步骤之前,我通常会进行一些额外的设置,以便根据我的偏好配置我的Rails应用程序,并包含我知道我将使用的宝石。我还找到了运行我的功能文件的逻辑顺序,因为有些文件依赖于其他文件。显然从身份验证开始。
然后我使用Rails生成器(脚手架或只是模型)来帮助我创建传递场景所需的代码。我改变了一些生成器模板,给了我想要的东西。
然后我根据需要调整生成的代码。大多数情况下,这涉及在模型中建立关系,使用视图中的关联以及脚手架无法提供的任何其他非标准功能。
我在必要时运行迁移
然后我重新运行我的场景并重复4-6中的任何步骤,直到场景通过。
重复步骤4-7,直到所有方案都通过。
我可能错了,但我认为很多人可能会使用类似的方法。让我烦恼的是,我在编写场景和生成/调整代码之间看到了很多重复。我希望能够使用我的黄瓜场景生成我的应用程序的skelaton,并使用步骤定义来帮助我自定义生成的内容。这是一个例子:
Scenario: MODEL widget exists
Given a widget model exists
Then it should belong to a "manufacturer"
And it should have a "quantity:integer" field
And it should validate the presence of "quantity"
And it should have many "wadgets"
And it should accept nested attributes for "wadgets"
#etc...
Scenario: VIEW new widget page
Given I am on the new widgets page
Then I should see a "quantity" field
And I should see a "wadgets:name" nested field
And I should see a button with text "Save Widget"
Scenario: CONTROLLER widget is created
Given a new widget is created
Then I should be on the widgets page
这将生成如下代码:
#FROM SCENARIO 1
class Widget < ActiveRecord::Base
has_many :wadgets
belongs_to :manufacturer
validates_presence_of :quantity
accepts_nested_attributes_for :wadgets
end
#FROM SCENARIO 1
class CreateWidget < ActiveRecord::Migration
def self.up
create_table :widgets do |t|
t.integer :quantity, :null=>false
t.integer :manufacturer_id
t.timestamps
end
end
def self.down
drop_table :widgets
end
end
#FROM SCENARIO 2
#new.html.haml (using formtastic helpers)
=semantic_form_for(@widget) do |f|
= f.inputs do
= f.input :quantity
= f.semantic_fields_for :wadgets do |wadget|
= location.input :name
= f.buttons
=f.commit_button "Save Widget"
#FROM SCENARIO 3 (using inherited resources)
class WidgetsController < InheritedResources::Base
def create
create!{ widget_urls }
end
end
现在这只是伪装,但我认为在Cucumber场景中定义应用程序然后根据这些场景中的内容生成代码将是一个真正的节省时间。这将允许您同时创建测试和编写代码。并且您不必键入scaffold生成器命令行的所有字段,它将自动设置关联并在视图中创建正确的字段类型。此外,它还允许您将整个功能设计保存在一个文件中。使用此方法,您将首先在场景上运行生成器,然后在生成后运行黄瓜测试。如果它设置正确,一切都会在第一次通过,你会有一个非常可靠的原型,你可以自定义。
是否有类似这种测试的插件?一代组合?
谢谢你花时间阅读这篇文章..我知道它有点长。
答案 0 :(得分:3)
几天前我有同样的想法。然而,在考虑了一些之后,我放弃了从特征文件生成模型的想法。相反,我正在使用dsl,它使用dsl中的rails生成器生成模型/脚手架/资源。
在我开始工作之后,我想在生成器中挂钩以基于dsl创建功能文件。
我有一个尖峰运行,它接受以下输入:
application :test do
model :survey do
attribute :name, :string
has_many :questions
end
model :question do
has_many :options
has_many :answers
belongs_to :survey
attribute :body, :string
end
model :option do
belongs_to :question
attribute :body, :string
attribute :selector, :string
end
model :result do
belongs_to :survey
has_many :answers
end
model :answer do
belongs_to :result
belongs_to :question
attribute :value, :string
end
gen
end
并打印以下输出:
rails new test
cd test
rails generate model survey name:string
rails generate model question survey_id:integer body:string
rails generate model option question_id:integer body:string selector:string
rails generate model result survey_id:integer
rails generate model answer result_id:integer question_id:integer value:string
Updating class: Survey
has_many:questions
Updating class: Question
belongs_to:survey
has_many:options
has_many:answers
Updating class: Option
belongs_to:question
Updating class: Result
belongs_to:survey
has_many:answers
Updating class: Answer
belongs_to:result
belongs_to:question
史蒂夫
答案 1 :(得分:2)
我认为你在这里使用黄瓜并不像预期的那样。
我假设我们都同意黄瓜功能应该描述客户想要看到的某些功能 - 它们基本上将故事卡(需求)转换为可运行的测试。这些故事不应该与模型,控制器和视图的实现有关。它应该测试诸如“当我点击按钮X时,我应该被带到第Y页,我的提交应该被批准。”这只是一个大型集成测试,可以模拟用户和您网站之间的交互。在您的示例中,您在页面上查找特定字段,可以通过说“当我用5填写数量字段时”来隐式检查。
为了测试模型的行为以及它们如何与业务逻辑交互,最好使用RSpec或Test :: Unit - 编写测试和模拟/存根更容易。我确信有些插件可以为模型中的每个字段/关系生成RSpec测试。 rspec-rails生成器已经完成了大部分工作,例如: rails generate rspec:scaffold Post
我认为对cucumber-rails的最佳改进是将模型和控制器测试留给RSpec,但随后能够为生成的黄瓜功能生成给定资源的标准CRUD操作,例如“用户应该能够创建一个X.“