Describe positive test in gherkin language - bdd

We're trying to express our requirements following the specification by example approach in the gherkin language. One part of the functionality is a check that under some conditions fails and should otherwise be positive. So we have many scenarios like this:
Given a <condition> //condition changes between scenario
When the check is performed
Then the result is negative
So after describing all the conditions under which check can fail, we would need one positive scenario like:
Given ... // this is what we're missing.
When the check is performed
Then the result is positive
We can't come up with a good way to formulate this one. Please note, this is part of a generic piece of functionality that can be extended by different products, so we can't just write: 'none of the above conditions apply'
Can any of you come up with a formulation that would mean something like Given there are no conflicting conditions, but is more testable?

Perhaps you could just do
When the check is performed
Then it works
It would be much better though if the scenarios talked about what is. Say we are signing in. I'd start with
When I sign in
Then I should be signed in
and then extend that for the sad paths
Given my email is invalid
When I sign in
Then I should not be signed in
All of the above would probably need some background e.g.
Given I am registered.
You don't have to have a given for every scenario
Here is an example imlementation for the Given
module RegistrationStepHelper do
def create_registered_user
# return a user who is registered and can sign in
...
def sign_in_as(user)
end
World RegistrationStepHelper
"Given I am registered" do
#i=create_registered_user
end
When "I sign in" do
sign_in_as: #i
end
...
for a slightly expanded example see here

Related

Rails –Testing named scopes: test scope results or scope configuration?

How should Rails named scopes be tested? Do you test the results returned from a scope, or that your query is configured correctly?
If I have a User class with an .admins method like:
class User < ActiveRecord::Base
def self.admins
where(admin: true)
end
end
I would probably spec to ensure I get the results I expect:
describe '.admins' do
let(:admin) { create(:user, admin: true) }
let(:non_admin) { create(:user, admin: false) }
let(:admins) { User.admins }
it 'returns admin users' do
expect(admins).to include(admin)
expect(admins).to_not include(non_admin)
end
end
I know that this incurs hits to the database, but I didn't really see any other choice if I wanted to test the scope's behaviour.
However, recently I've seen scopes being specced by confirming that they're configured correctly, rather than on the result set returned. For this example, something like:
describe '.admins' do
let(:query) { User.admins }
let(:filter) { query.where_values_hash.symbolize_keys }
let(:admin_filter) { { admin: true } }
it 'filters for admin users' do
expect(filter).to eq(admin_filter) # or some other similar assertion
end
end
Testing the direct innards of a query like this hadn't really occurred to me before, and on face value it is appealing to me since it doesn't touch the database, so no speed hit incurred.
However, it makes me uneasy because:
it's making a black-box test grey(er)
I have to make the assumption that because something is configured a certain way, I'll get the results that my business logic requires
The example I've used is so trivial that perhaps I'd be okay with just testing the configuration, but:
where do you draw the line and say 'the content of this named scope is too complex and requires result confirmation tests over and above just scope configuration testing'? Does that line even exist or should it?
Is there a legitimate/well-accepted/'best practice' (sorry) way to test named scopes without touching the database, or at least touching it minimally, or is it just unavoidable?
Do you use either of the above ways to test your scopes, or some other method entirely?
This question(s) is a bit similar to Testing named scopes with RSpec, but I couldn't seem to find answers/opinions about testing scope results vs scope configuration.
I think you have described the problem very well, and that the best answer, in my opinion is - it depends.
If your scope is trivial, run-of-the-mill where, with some order, etc. there is no real need to test ActiveRecord or the database to make sure they work properly - you can safely assume that they have been correctly implemented, and simply test the structure you expect.
If, on the other hand, your scope (or any query) is compound, or uses advanced features in a complex configuration, I believe that setting up tests that assert its behavior, by using a real live database (which is installed locally, with a small custom-tailored data set) can go a long way in assuring you that your code works.
It will also help you, if and when you decide to change strategies (use that cool new mysql feature, or porting to postgresql), to refactor safely, by checking that the functionality is robust.
This is a much better way than to simply verify the the SQL string is what you typed there...

How to test a random uniq values with rspec

I have this code:
def self.generate_random_uniq_code
code = sprintf("%06d", SecureRandom.random_number(999999))
code = self.generate_random_uniq_code if self.where(code: code).count > 0
code
end
The goal is create random codes for a new register, the code can't exist already in the registers
I'm trying test this way, but when I mock the SecureRandom it always return the same value:
it "code is unique" do
old_code = Code.new
old_code.code = 111111
new_code = Code.new
expect(SecureRandom).to receive(:random_number) {old_code.code}
new_code.code = Code.generate_random_uniq_code
expect(new_code.code).to_not eq old_code.code
end
I was trying to find if there is a way to enable and disable the mock behavior, but I could not find it, I'm not sure I'm doing the test the right way, the code seems no work fine to me.
Any help is welcome, thanks!
TL;DR
Generally, unless you are actually testing a PRNG that you wrote, you're probably testing the wrong behavior. Consider what behavior you're actually trying to test, and examine your alternatives. In addition, a six-digit number doesn't really have enough of a key space to ensure real randomness for most purposes, so you may want to consider something more robust.
Some Alternatives
One should always test behavior, rather than implementation. Here are some alternatives to consider:
Use a UUID instead of a six-digit number. The UUID is statistically less likely to encounter collisions than your current solution.
Enforce uniqueness in your database column by adjusting the schema.
Using a Rails uniqueness validator in your model.
Use FactoryGirl sequences or lambdas to return values for your test.
Fix Your Spec
If you really insist on testing this piece of code, you should at least use the correct expectations. For example:
# This won't do anything useful, if it even runs.
expect(new_code.code).to_not old_code.code
Instead, you should check for equality, with something like this:
old_code = 111111
new_code = Code.generate_random_uniq_code
new_code.should_not eq old_code
Your code may be broken in other ways (e.g. the code variable in your method doesn't seem to be an instance or class variable) so I won't guarantee that the above will work, but it should at least point you in the right direction.

Multiple should statements in one rspec it clause - bad idea?

Here's my rspec test:
it "can release an idea" do
james.claim(si_title)
james.release(si_title)
james.ideas.size.should eq 0
si_title.status.should eq "available"
end
Are the two should lines at the end a really bad idea? I read somewhere that you should only test for one thing per it block, but it seems silly to make a whole test just to make sure that the title status changes (the same function does both things in my code).
My interpretation of this isn't so much that there should be precisely one assertion / call to should per spec, but that there should only be one bit of behaviour tested per spec, so for example
it 'should do foo and bar' do
subject.do_foo.should be_true
subject.do_bar.should be_true
end
is bad - you're speccing 2 different behaviours at the same time.
on the other hand if your 2 assertions are just verifying different aspects of one thing then I'm ok with that, for example
it 'should return a prime integer' do
result = subject.do_x
result.should be_a(Integer)
result.foo.should be_prime
end
For me it wouldn't make too much sense to have one spec that checks that it returns an integer and a separate one that it returns a prime.
Of course in this case, the be_prime matcher could easily do both of these checks - perhaps a good rule of thumb is that multiple assertions are ok if you could sensibly reduce them to 1 with a custom matcher (whether actually doing this is actually worthwhile probably depends on your situation)
In your particular case, it could be argued that there are 2 behaviours at play - one is changing the status and other is mutating the ideas collection. I would reword your specs to say what the release method should do -
it 'should change the status to available'
it 'should remove the idea from the claimants ideas'
At the moment those things always happen simultaneously but I would argue they are separate behaviours - you could easily imagine a system where multiple people can claim/release an idea and the status only change when the last person releases the idea.
I have the same problem...
It ought to be one should per it (my boss says) by it makes testing time consuming and, as you said, silly.
Tests require good sense and flexibility or they might end up enslaving you.
Anyway, I agree with your test.
My policy is to always consider multiple assertions to be a sign of a potential problem and worth a second thought, but not necessarily wrong. Probably 1/3 of the specs I write end up having multiple assertions in them for one reason or another.
One of the problems with having multiple assertions is that when one fails, you can't see if the other one passed or not. This can sometimes be worked around by building an array of results and asserting the value of the array.
In the case you are asking about, I don't think that multiple assertions are a problem, but I do see something else that seems an issue to me. It looks like your spec may be overly coupled.
I think that you're trying to assert the behavior of whatever kind of a thing james is, but the test is also depending on behavior of si_title in order to tell us what was done to it (by way of its eventual #status value). What I would usually do instead is make si_title a test-double and use #should_receive to directly specify the messages that it should expect.
I think Frederick Cheung gave a very good answer (+1) especially the why, but I'd also like to give a comparison bit of code for you to look at which uses the its, lets, before and context syntax:
context "Given a si_title" do
let(:james) { James.new } # or whatever
before do
james.claim(si_title)
james.release(si_title)
end
context "That is valid" do
let(:si_title) { Si_title.new } # or whatever
describe "James' ideas" do
subject { james.ideas }
its(:size) { should == 0 }
its(:whatever) { should == "Whatever" }
end
describe "Si title" do
subject { si_title }
its(:status) { should == "available" }
end
end
context "That is invalid" do
# stuff here
end
end
I would even go further and make the expected values lets and then make the examples shared_examples, so that they could then be use to check the different aspects (null arguments, invalid arguments, an incorrect object… ), but I believe that this is a far better way to spec your intentions and still cut down on any repetition. Taking the example from Frederick's answer:
it 'should return a prime integer' do
result = subject.do_x
result.should be_a(Integer)
result.foo.should be_prime
end
Using RSpec's syntax to full effect you get this:
let(:result) { 1 }
subject{ result }
its(:do_x) { should be_a(Integer) }
its(:foo) { should be_prime }
Which means you can check multiple aspects of a subject.

Rails assert that form is valid

What's the best practices way to test that a model is valid in rails?
For example, if I have a User model that validates the uniqueness of an email_address property, how do I check that posting the form returned an error (or better yet, specifically returned an error for that field).
I feel like this should be something obvious, but as I'm quickly finding out, I still don't quite have the vocabulary required to effectively google ruby questions.
The easiest way would probably be:
class UserEmailAddressDuplicateTest < ActiveSupport::TestCase
def setup
#email = "test#example.org"
#user1, #user2 = User.create(:email => #email), User.new(:email => #email)
end
def test_user_should_not_be_valid_given_duplicate_email_addresses
assert !#user2.valid?
end
def test_user_should_produce_error_for_duplicate_email_address
# Test for the default error message.
assert_equal "has already been taken", #user2.errors.on(:email)
end
end
Of course it's possible that you don't want to create a separate test case for this behaviour, in which case you could duplicate the logic in the setup method and include it in both tests (or put it in a private method).
Alternatively you could store the first (reference) user in a fixture such as fixtures/users.yml, and simply instantiate a new user with a duplicate address in each test.
Refactor as you see fit!
http://thoughtbot.com/projects/shoulda/
Shoulda includes macros for testing things like validators along with many other things. Worth checking out for TDD.
errors.on is what you want
http://api.rubyonrails.org/classes/ActiveRecord/Errors.html#M002496
#obj.errors.on(:email) will return nil if field is valid, and the error messages either in a String or Array of Strings if there are one or more errors.
Testing the model via unit tests is, of course, step one. However, that doesn't necessarily guarantee that the user will get the feedback they need.
Section 4 of the Rails Guide on Testing has a lot of good information on functional testing (i.e. testing controllers and views). You have a couple of basic options here: check that the flash has a message in it about the error, or use assert_select to find the actual HTML elements that should have been generated in case of an error. The latter is really the only way to test that the user will actually get the message.

How to write stories / scenarios in BDD ( Behavior Driven Design )

I am about to use BDD (Behavior Driven Design) for the first time and am trying to get used to this different way of approaching a problem.
Can you give some stories / scenarios that you would write for say a simple login application using BDD?
For example, from what I have read, it seems that is good:
When a user enters an invalid userid/password, then display an error
message.
As opposed to:
Validate id and password by searching for a matching record in the
database.
Dan North has some excellent advice on writing stories. "Dan North- What's in a Story?"
I would also take a look at some of the work being done around Cucumber as they have spent a lot of time thinking about how to write these stories in an understandable and executable way.
Dan North's article that _Kevin mentioned is great.
Remember, though, that there are "user stories," which should actually be written or at least collected from the client/users. These are more of the "As a , I want , so that " type stories.
Then there are acceptance criteria, which identify how and when the user story will be said to be satisfied. That is like what you have written in your post: "When x, it should y."
There is a lot of overlap here with what I call "system stories" in my project management system and "specifications" in my tests which specify behaviour that the user may not be aware of, but describe interaction between your classes.
System story: "When the LoginHandler is given a login and password, it should validate the data with a LoginValidator."
Specification:
[TestFixture]
public class When_the_login_handler_is_given_a_login_and_password
{
constant string login = "jdoe";
constant string password = "password";
static LoginValidator loginValidator;
context c = () => loginValidator = an<ILoginValidator>;
because b = () => sut.Validate(login, password);
it should_validate_the_data_with_a_LoginValidator =
() => loginValidator.was_told_to(x => x.DoValidation(login, password));
}
Nevermind the testing syntax, you can see that the specification text itself is embodied in the test class name and method name. Furthermore, the test/spec is actually testing the behaviour of the classes. When tests like this pass for simple user stories, the acceptance criteria has been met.
I found an awesome talk here https://skillsmatter.com/skillscasts/2446-bdd-as-its-meant-to-be-done
(caution, you need to create an account to view the video)

Resources