it would be great if somebody could help me with the cucumber/pickle syntax on creating
related objects and assert them.
How can I get references in my cucumber syntax...
Something Like
For example: creating a blog post with a certain title with 3 comments
And then assert this post and the related comments...
Is this with object builder by pickle possible or do I have to write these steps manually
and how do I reference the value from master in detail?
I am looking especially for reffering Object in different steps and inserting master with its details in one batch with pickle (without defining the step manually) and then asserting it....
I should have 1 blogpost with 3 comments...
Check out the following screen-casts:
http://railscasts.com/episodes/155-beginning-with-cucumber
http://railscasts.com/episodes/159-more-on-cucumber
http://railscasts.com/episodes/186-pickle-with-cucumber
These put me well on my way to cucumber and pickle goodness
Good luck!
Related
I just, manually, discovered a migration error. I added a new field to a model, and forgot to add it into the model_params method of the controller. As a result the new field wasn't persisted to the database.
Easy enough to fix once I noticed the problem, but it got me to wondering if there was a way to detect this in testing. I would imagine something like a gem that would parse the schema and generate a set of tests to ensure that all of the fields could be written and that the same data could be read back.
Is this something that can be (or is) done? So far, my searches have led me to lots of interesting reading, but not to a gem like this...
It is possible to write what you would want. Iterate through all the fields in the model, generate params that mirrors those fields, and then run functional tests on your controllers. The problem is that the test is brittle. What if you don't actually want all the fields to be writable through params? What if you reference a model in another controller outside of the standard pattern? How will you handle generating data that would pass different validations? You would either have to be sure that your application would only be written in a certain way or this test would become more and more complex to handle additional edge cases.
I think the solution in testing would be to try to keep things simple; realize that you've made a change to the system and as a result of that change, corresponding tests would need to be updated. In this case, you would update the functional and unit tests affected by that model. If you were strictly adhering to Test Driven Design, you would actually update the tests first to produce a failing test and then implement the change. As a result, hopefully the updated functional test would have failed in this case.
Outside of testing, you may want to look into a linter. In essence, you're asking if you can catch an error where the parameters passed to an object's method doesn't match the signature. This is more catchable when parsing the code completely (i.e. compilation in a static type environment).
EDIT - I skipped a step on the linting, as you would also have to write your code a certain way that a linter would catch it, such as being more explicit of the method and parameters passed to it.
You might want to consider that such a gem may not exist because its not that practical or useful in real life.
Getting the columns off a model is pretty simple from the reflection methods that Active Record gives you. And yeah you could use that theoretically to automagically run a bunch of tests in loop.
But in reality its just not going to cut it. In real life you don't want every column to be assignable. Thats why you are using mass assignment protection in the first place.
And add to that the complexity of the different kinds of constraints and data types your models have. You'll end up with something extremely complex with just adds a bunch of tests with limited value.
If you find yourself omitting a property from mass assignment protection than your should try to cover that part of your controller either with a functional test or an integration test.
class ArticlesControllerTest < ActionController::TestCase
def valid_attributes
{
title: 'How to test like a Rockstar',
content: 'Bla bla bla'
}
end
test "created article should have the correct attributes" do
post :create, article: valid_attributes
article = Article.last
valid_attributes.keys.each do |key|
assert_equals article[key], valid_attributes[key]
end
end
end
I've got a model List with nested attributes from another one, Article. What bugs me is I have Ruby request params having my first nested attribute in Article hash, and all the others(2nd,3rd article data, etc) in article_parameters.
I follow the standard mongoid tutorial here.
I have #list.articles.build in create method of List controller.
Can I influence what goes into build method? I've tried to call build(all_the_correct_hashes) but it does not seem to fix the issue.
So, in the nutshell I have 2 questions.
why articles gets only the first nested attribute, 2nd and next go to article_parameters hash?
why list.articles.build only creates _id in my Mongo document, but does not populate it with other fields?
I'll write up my solution, since I see people upvoting my question.
Frankly, I did not find any answer as to why such behaviour occurs.
The solution is a bit hackish.
In your save controller, call List.article.build(id => params[:id], someotherstuff => params[:someotherstuff])
Everything you pass to build in this case will populate article_parameters hash.
id and sometherstuff are fields of my Article model.
I feel this should be done implicitly by Mongoid, but it just does not work. Their development does not see anything wrong with it, either.
Is there any way to auto-generate simple test cases? I found myself spending time writing very simple tests that make sure all controllers and models are working fine. Here is an example of controller test case written with rspec:
machine = FactoryGirl.create(:machine, type: 1)
mac = FactoryGirl.create(:mac, machine_id: m1.id)
win = FactoryGirl.create(:win, machine_id: m4.id)
sign_in user
get :index
get :show, id: machine.id
get :report
I cannot find any tool today that can auto-generate such tests based on new written code. If really nothing exists, I may consider building a solution to this problem.
If a test were predictable enough to generate it wouldn't be worth writing. In your example, you don't assert anything. That's a very weak test, good only for raising code coverage. It would be much stronger if it asserted what should be on the page. You can't generate that. You also can't generate a scenario that traverses multiple pages in a meaningful way. (I think your example wants to be an rspec feature spec or a Cucumber scenario.)
It would make sense to write a generator that creates a skeleton that the developer could fill in with the meaningful parts that can't be generated, however.
To cover basic functionality you could write a specific generator.
You can also redefine standard scaffold templates (for example, by adding your own template to lib/templates/rspec/model/model_spec.rb - this will redefine model scaffolding).
But the real question is why to do so. Following TDD you should write the test and then create your code, not vice versa.
I am looking for a Ruby/Rails tool that will help me accomplish the following:
I would like to store the following string, and ones similar to it, in my database. When an object is created, updated, deleted, etc., I want to run through all the strings, check to see if the CRUD event matches the conditions of the string, and if so, run the actions specified.
When a new ticket is created and it's category=6 then notify user 1234 via email
I am planning to create an interface that builds these strings, so it doesn't need to be a human-readable string. If a JSONish structure is better, or a tool has an existing language, that would be fantastic. I'm kinda thinking something along the lines of:
{
object_types: ['ticket'],
events: ['created', 'updated'],
conditions:'ticket.category=6',
actions: 'notify user',
parameters: {
user:1234,
type:'email'
}
}
So basically, I need the following:
Monitor CRUD events - It would be nice if the tool had a way to do this, but Ican use Rails' ModelObservers here if the tool doesn't natively provide it
Find all matching "rules" - This is my major unknown...
Execute the requested method/parameters - Ideally, this would be defined in my Ruby code as classes/methods
Are there any existing tools that I should investigate?
Edit:
Thanks for the responses so far guys! I really appreciate you pointing me down the right paths.
The use case here is that we have many different clients, with many different business rules. For the rules that apply to all clients, I can easily create those in code (using something like Ruleby), but for all of the client-specific ones, I'd like to store them in the database. Ideally, the rule could be written once, stored either in the code, or in the DB, and then run (using something Resque for performance).
At this point, it looks like I'm going to have to roll my own, so any thoughts as to the best way to do that, or any tools I should investigate, would be greatly appreciated.
Thanks again!
I don't think it would be a major thing to write something yourself to do this, I don't know of any gems which would do this (but it would be good if someone wrote one!)
I would tackle the project in the following way, the way I am thinking is that you don't want to do the rule matching at the point the user saves as it may take a while and could interrupt the user experience and/or slow up the server, so...
Use observers to store a record each time a CRUD event happens, or to make things simpler use the Acts as Audited gem which does this for you.
1.5. Use a rake task, running from your crontab to run through the latest changes, perhaps every minute, or you could use Resque which does a good job of handling lots of jobs
Create a set of tables which define the possible rules a user could select from, perhaps something like
Table: Rule
Name
ForEvent (eg. CRUD)
TableInQuestion
FieldOneName
FieldOneCondition etc.
MethodToExecute
You can use a bit of metaprogramming to execute your method and since your method knows your table name and record id then this can be picked up.
Additional Notes
The best way to get going with this is to start simple then work upwards. To get the simple version working first I'd do the following ...
Install acts as audited
Add an additional field to the created audit table, :when_processed
Create yourself a module in your /lib folder called something like processrules which roughly does this
3.1 Grabs all unprocessed audit entries
3.2 Marks them as processed (perhaps make another small audit table at this point to record events happening)
Now create a rules table which simply has a name and condition statement, perhaps add a few sample ones to get going
Name: First | Rule Statement: 'SELECT 1 WHERE table.value = something'
Adapt your new processrules method to execute that sql for each changed entry (perhaps you want to restrict it to just the tables you are working with)
If the rule matched, add it to your log file.
From here you can extrapolate out the additional functionality you need and perhaps ask another question about the metaprogramaming side of dynamically calling methods as this question is quite broad, am more than happy to help further.
I tend to think the best way to go about task processing is to setup the process nicely first so it will work with any server load and situation then plug in the custom bits.
You could make this abstract enough so that you can specify arbitrary conditions and rules, but then you'd be developing a framework/engine as opposed to solving the specific problems of your app.
There's a good chance that using ActiveRecord::Observer will solve your needs, since you can hardcode all the different types of conditions you expect, and then only put the unknowns in the database. For example, say you know that you'll have people watching categories, then create an association like category_watchers, and use the following Observer:
class TicketObserver < ActiveRecord::Observer
# observe :ticket # not needed here, since it's inferred by the class name
def after_create(ticket)
ticket.category.watchers.each{ |user| notify_user(ticket, user) }
end
# def after_update ... (similar)
private
def notify_user(ticket, user)
# lookup the user's stored email preferences
# send an email if appropriate
end
end
If you want to store the email preference along with the fact that the user is watching the category, then use a join model with a flag indicating that.
If you then want to abstract it a step further, I'd suggest using something like treetop to generate the observers themselves, but I'm not convinced that this adds more value than abstracting similar observers in code.
There's a Ruby & Rules Engines SO post that might have some info that you might find useful. There's another Ruby-based rules engine that you may want to explore that as well - Ruleby.
Hope that this helps you start your investigation.
I'm new to Ruby and recently ran into an issue comparing to values when creating a Ruby on Rails application. In a controller I had the following statement that always returned false:
if (user.id != params[:id])
The problem was the user.id (which is an Active Record) is an integer and params[:id] is a string. It took me a while to figure this out and I finally changed it to:
if (user.id != params[:id].to_i)
Now the statement works as expected.
To avoid this error in the future is there a way to "compile" or get Ruby to warn you if you try to compare 2 different types? Some other issues I've ran into that I would like to "compile check" are:
Warn me if I create a variable but don't use it. To help check for typos in variable names.
Make sure a method exists in a Class so I can avoid method name typos and also to help refactoring, for example if I rename a method.
I'm currently using Ruby 1.8.6-27 RC2 with Rails 2.3.2 and RadRails IDE on Windows.
Test first, then code. If you write tests that cover all branches of your application, you get the assurance that your code both runs and produces correct results.
EDIT: I should point out that the ability to compare two types, not depend on method names until the last second, etc. are core features of Ruby.
You don't call a method so much as you send a message to an object. The object is then responsible for figuring out how to handle the method. In Rails this is used to access DB columns in ActiveRecord. There are no methods for the columns until a message with the column name is sent to the object.
Static typing in Ruby goes against the duck typing system. One can often get polymorphism for free without worrying about complex inheritance/interface schemes.
I suggest embracing these features and compensate for the uncertainty through testing
Ruby doesn't allow you to redefine the == operator for Object. In ruby 1.8 you can't, Ruby 1.9 was supposed to do but I haven't been able to get my script working for core classes. It works well for custom defined objects.
class Object
alias :equal_without_warning :==
def ==(object)
unless self.class == object.class
warn("Comparing `#{self.class}' with `#{object.class}'")
end
equal_without_warning(object)
end
end
Assuming I didn't do some stupid coding error, the answer is NO: you can't check whether you are comparing different type of objects.
Also, I would say you don't. Actually Ruby isn't designed to work in this way, this is more a java approach rather than Ruby style.
Ruby isn't supposed to be safe. It lets you compare any two objects, and that's where much of its power comes from. Rails wouldn't be possible without such dynamic design.
Even a compiled language such as Java or C won't stop you from doing == on two objects. As Ben said, it's best to test first. Inspect the structures you're working with. One way to get information about a Ruby object is to use:
puts object.class
In general, the best way (I know of) to avoid this type of issue for dynamic/scripting languages is to move "logic" to methods/commands and write unit tests for them. Basically, anything that can fail should be tested. The code on the page should be dumb logic... rather than display only those items that meet a certain criteria, it should display all items, and get that list of items from a method that only returns the ones that should be displayed.
Two things I'd suggest:
One: Read up on IRB (or script/console for rails). A common development practice in dynamic languages is to try out snippets of code inside a "live" interpreter (like IRB or the rails console). This practice goes back to the earliest dynamic languages like Smalltalk and Lisp. Ruby-debug is also really useful for troubleshooting problems and would have been a really easy way to figure out the error in your example.
Two: Read up on "Duck Typing". "Types" and variables work a little bit differently in Ruby than many folks expect them to. As I understand it, a variable like user.id doesn't have a "type". The value pointed to by user.id does have a type, but the variable itself doesn't. I believe that's part of why there's no tool that would have told you what your error was in advance of running the program. Comparing those two variables isn't an error because the variables don't have a type. user.id was pointing to an integer at that point in your program, but it would be perfectly legal to assign user.id to point to a string, at which point that comparison would have made a lot more sense. :-)
The best solution I found was a IDE that did on-the-fly syntax checking, such as RubyMine. I'm not sure if it would have solved my original problem but it has helped me find and fix several other syntax and compile errors. Thank you everyone for your suggestions.