I am planning on creating a plugin that will generate app code based on Cucumber scenarios, but I want to make sure I am not reinventing the wheel here. Is anyone aware of a plugin that works with Cucumber and generates models, controllers and views?
Just a little background on what I am trying to do in case this doesn't make sense. When I create a new application here is my workflow:
Sketch out 2 types of high level designs on my whiteboard. 1 that shows models and relationships and another that shows some primitive screens for layouts, forms, etc.
Write cucumber scenarios based on the high level design (but finer grained). Many of these steps just describe what I will see on a particular view and also outline the flow of the application. I find that creating all the scenarios I can think of before I start coding is better than doing one at a time and coding after writing each scenario.
I run the cucumber scenarios and look at the first failure and start coding from there. I usually have some additional setup before this step to configure my Rails app to my preferences and include gems that I know I will use. I also find a logical order to run my feature files since some are dependent on others. Obviously starting with things like authentication.
Then I use Rails generators (scaffold or just model) to help me create the code I need to pass a scenario. I alter some of the generator templates to give me what I want.
Then I tweak the generated code if necessary. Most of the times this involves setting up relationships in the model, working with the associations in the views, and any other non-standard functionality that scaffolding can't provide.
I run my migrations if necessary
Then I rerun my scenarios and repeat any steps in 4-6 until the scenario passes.
Repeat steps 4-7 until all scenarios pass.
I may be wrong, but I think alot of people probably use an approach similar to this. The thing that annoys me is that I see alot of duplication between writing the scenarios and generating/tweaking code. I want to be able to generate the skelaton of my app with my cucumber scenarios and use the step definitions to help me customize what is generated. Here is an example:
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
This would generate code like so:
#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
This is just psuedo at this point, but I think it would be a real time-saver to define your application in Cucumber scenarios and then generate the code based on what is in these scenarios. This would allow you to create tests and write code at the same time. And you would not have to type out all of the fields for the scaffold generator command line, and it would automatically set the associations and create the proper fields types in the view. Also, it would allow you to keep your entire feature design in one file. Using this approach, you would run the generator first on the scenario and then run the cucumber tests after the generation. If it was set up correctly, everything would pass the first time and you would have a pretty solid prototype that you could customize.
Are there any plugins that resemble this kind of testing & generation combo?
And thanks if you took the time to read this.. I know it was a bit long.
I had the same idea a couple of days ago. However, after thinking about it some more, I abandon the ideas of generating the models from the feature files. Instead, I'm playing with a dsl that generates the models/scaffold/resources using the rails generator from the dsl.
After I get this working, I was thinking of hooking in generators to create feature files based on the dsl.
I have a spike running that takes the following input:
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
and prints the following output:
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
Steve
I think your use of cucumber here is not as it was intended.
I'm assuming we all agree that cucumber features should describe certain features that the customer wants to see - they basically translate story cards (requirements) into runnable tests. These stories should not be concerned with the implementation of your models, controllers, and views. It should test things like "when I click button X, I should be taken to page Y, and my submission should be approved." It's just one big integration test that simulates the interaction between the user and your site. In your example, you look for specific fields on the page, which could be implicitly checked by saying "when I fill in the quantity field with 5."
For testing the behavior of models and how they interact with business logic, you would be better off using RSpec or Test::Unit - it's much easier to write tests and do mocking/stubbing. I'm sure there are plugins that generate RSpec tests for each field/relationship in your model. The rspec-rails generators already to most of the work for you, e.g. rails generate rspec:scaffold Post
I think the best improvement to cucumber-rails would be to leave the model and controller testing to RSpec, but then be able to generate standard CRUD actions for a given resource with generated cucumber features, like "A user should be able to create an X."
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With