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)
Related
It said here https://www.relishapp.com/rspec/rspec-core/v/3-5/docs/helper-methods/let-and-let what variable defined by let is changing across examples.
I've made the same simple test as in the docs but with the AR model:
RSpec.describe Contact, type: :model do
let(:contact) { FactoryGirl.create(:contact) }
it "cached in the same example" do
a = contact
b = contact
expect(a).to eq(b)
expect(Contact.count).to eq(1)
end
it "not cached across examples" do
a = contact
expect(Contact.count).to eq(2)
end
end
First example passed, but second failed (expected 2, got 1). So contacts table is empty again before second example, inspite of docs.
I was using let and was sure it have the same value in each it block, and my test prove it. So suppose I misunderstand docs. Please explain.
P.S. I use DatabaseCleaner
P.P.S I turn it off. Nothing changed.
EDIT
I turned off DatabaseCleaner and transational fixtures and test pass.
As I can understand (new to programming), let is evaluated once for each it block. If I have three examples each calling on contact variable, my test db will grow to three records at the end (I've tested and so it does).
And for right test behevior I should use DatabaseCleaner.
P.S. I use DatabaseCleaner
That's why your database is empty in the second example. Has nothing to do with let.
The behaviour you have shown is the correct behaviour. No example should be dependant on another example in setting up the correct environment! If you did rely on caching then you are just asking for trouble later down the line.
The example in that document is just trying to prove a point about caching using global variables - it's a completely different scenario to unit testing a Rails application - it is not good practice to be reliant on previous examples to having set something up.
Lets, for example, assume you then write 10 other tests that follow on from this, all of which rely on the fact that the previous examples have created objects. Then at some point in the future you delete one of those examples ... BOOM! every test after that will suddenly fail.
Each test should be able to be tested in isolation from any other test!
I am new to selenium tests in grails. I am using geb and spock for testing.
I want to split my test plans into some smaller test plans. I want to know if it's possible to make a spec which calls other specs?
What you should do it have a 'Spec' for each area of the application. If that area has more than one scenarios then include them in the 'Spec' that matches that area.
For Example.
LogInSpec
Has a log in scenario.
Form validation scenario.
Log out scenario.
This way things stay organized and its easy to see what sections of your application are failing.
If your goal is to run these in parallel then I recommend that you try and keep tests even across the different test classes. This way they all take around the same amount of time.
You can create traits for each of the modules ,
Exp: consider validations of entering details in form:
Name,Contact details and other comments
Create a trait which has methods to fill these details and verify after saving these details
Use this trait in your spec.
This will make your code more readable and clear
I found now another solution.
I make a simple groovy class:
class ReUseTest {
def myTest(def spec) {
when:
spec.at ConnectorsPage
then:
spec.btnNewConnector.click()
}
In my spec I can call this this like:
def "MyTest"() {
specs.reuseable.ReUseTest myTest = new specs.reuseable.ReUseTest()
specs.myTest(this)
}
I can now use this part in every spec.
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
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...
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.