The After hook in cucumber - ruby-on-rails

Folks,
I am having some trouble working with the Afterhook. I have organized my tests in folders like this:
features/Accounts/accounts_api.feature
features/Accounts/step_definition/account_steps.rb
features/labs/create_lab.feature
features/labs/step_definition/labs_steps.rb
Now I have an After hook present in the step definition of the Accounts feature, I want that hook to run after every scenario of the "Accounts" feature, but I do not want it to run after every scenario of the "labs" feature. I tried this:
cucumber --tags #newlabs
the above should run all the scenarios present in the labs feature tagged as newlabs but what I am seeing is that once the scenario tagged as#newlabs runs the #after hook present in the step definition of Accounts starts to run. I am thinking why is this happening, am I using the hook in the wrong way or is my overall understanding of hooks wrong?
Thanks a lot for taking the time to respond, this helps a lot.

Hooks don't care what step definition script they're located in and will run for every scenario. Or, more specifically, your after hook will run after every scenario that runs, for every feature, regardless of the tags you pass in to Cucumber.
If you want a little more control over that, check out the Cucumber wiki page on hooks and look in the section called 'Tagged hooks'.

Possibly you define After hook in wrong place. Note that After hook (as well as other hooks) must be defined in the .rb, not in the .feature file. Common place for hooks is features/support/hooks.rb. You will define your hook this way:
# features/support/hooks.rb
After('#newlabs') do # will run after each scenario tagged with #newlabs
# your teardown ruby code
end
# features/Accounts/accounts_api.feature
#newlabs # tag all scenarious of this feature with #newlabs tag
Feature: your feature
Scenario: your scenario
Given: ...
When: ...
Then: ...
In cucumber output you won't see that After hook is executed (unless you output something to STDOUT from the hook definition) - hooks will run implicitly.

Related

Grails Test Suite - Specify test order

I am trying to get my geb-spock functional tests to run in a specified order because SpecA will create data required for SpecB during its run.
This question is about running the specifications in order, not the individual test methods within the specification.
I have tried changing the specification name to indicate execution order but that didn't work. I found a solution where a Test Suite was used, and the tests were added to the suite in order, but I can't find how to make a test suite work in Grails.
Explicitly specifying them as grails test-app functional: SpecA SpecB , is not a long term option, as more specs will be added.
For sequential or whatever the sequence you want to run your tasks, I do the following thing in my build.gradle file:
def modules = ["X", "Y", "Z", "ZZ"]
if (modules.size() > 1) {
for(j in 1 .. modules.size()-1 ) {
tasks[modules[j]].mustRunAfter modules[values[j-1]]
}
}
Hope that helps. Cheers!
Not really an answer to your question but a general advice - don't do this. Introducing data setup dependencies between test classes will make your suite brittle in the long run. Reasoning about what the state is at a given point will get harder and harder as the amount of tests grows and the global state size with it. Later on hanging a test or introducing a new one might break many tests downstream. This is just asking for trouble.
Ideally, you want to setup the data needed by a test immediately before that test and tear it down afterwards. Grails Remote Control plugin and test data fixture builders are your friends here.
You should define your initialization code in a single place, and if it's shared between both Specs, it may be a good idea to create a superclass with methods you can call in each Spec's set up methods, or a whole class devoted to declare testing methods to reuse.
In any case, the purpose of a unit test is only to test a single functionality, and it shouldn't be responsible of setting up other tests as well.

After hook for the entire feature in cucumber

In cucucmber i want to run a step after all the scenarios in a feature are run, can I have an after hook for the entire feature, I currently have after hooks for each scenario.
I know its been a long time, but i havent been a user here for long but,
There is an exit hook that is used like this:
at_exit do
# Add code here
end
This should be placed in your env.rb file or the features/support directory
Here's a great link
It's a bit of a workaround, but you could just have scenarios at the beginning and the end of the feature for setup/teardown. Scenarios are run in the order that they are specified so as long as you have the setup scenario at the top and the teardown at the bottom then it works fine.
I also name the Scenario 'Scenario: feature setup' and 'Scenario: feature teardown' to make it more obvious when outputting the results to a formatter.
You can use a custom formatter, and use the after_feature method.
(I used to have a link with more information, but #katta just pointed out that its no longer available)
Sure, just tag your feature.
After('#mytag') do
#Do your magic here
end
This documentation might help: http://cukes.info/cucumber/api/ruby/latest/Cucumber/RbSupport/RbDsl.html#AfterStep-instance_method

Cucumber step to pause and hand control over to the user

I'm having trouble debugging cucumber steps due to unique conditions of the testing environment. I wish there was a step that could pause a selenium test and let me take over.
E.g.
Scenario: I want to take over here
Given: A bunch of steps have already run
When: I'm stuck on an error
Then: I want to take control of the mouse
At that point I could interact with the application exactly as if I had done all the previous steps myself after running rails server -e test
Does such a step exist, or is there a way to make it happen?
You can integrate ruby-debug into your Cucumber tests. Nathaniel Ritmeyer has directions here and here which worked for me. You essentially require ruby-debug, start the debugger in your environment file, and then put "breakpoint" where ever you want to see what's going on. You can both interact with the browser/application and see the values of your ruby variables in the test. (I'm not sure whether it'll let you see the variables in your rails application itself - I'm not testing against a rails app to check that).
I came up with the idea to dump the database. It doesn't let you continue work from the same page, but if you have the app running during the test, you can immediately act on the current state of things in another browser (not the one controlled by Selenium).
Here is the step:
When /I want to take control/i do
exec "mysqldump -u root --password=* test > #{Rails.root}/support/snapshot.sql"
end
Because it is called by exec, DatabaseCleaner has no chance to truncate tables, so actually it's irrelevant that the command is a database dump. You don't have to import the sql to use the app in its current state, but it's there if you need it.
My teammate has done this using selenium, firebug a hook (#selenium_with_firebug)
Everything he learned came from this blogpost:
http://www.allenwei.cn/tips-add-firebug-extension-to-capybara/
Add the step
And show me the page
Where you want to interact with it
Scenario: I want to take over here
Given: A bunch of steps have already run
When: I'm stuck on an error
Then show me the page
use http://www.natontesting.com/2009/11/09/debugging-cucumber-tests-with-ruby-debug/
Big thank you to #Reed G. Law for the idea of dumping the database. Then loading it into development allowed me to determine exactly why my cucumber feature was not impacting database state as I had expected. Here's my minor tweak to his suggestion:
When /Dump the database/i do
`MYSQL_PWD=password mysqldump -u root my_test > #{Rails.root}/snapshot.sql`
# To replicate state in development run:
# `MYSQL_PWD=password mysql -u root my_development < snapshot.sql`
end
You can also use the following in feature/support/debugging.rb to let you step through the feature one step at a time:
# `STEP=1 cucumber` to pause after each step
AfterStep do |scenario|
next unless ENV['STEP']
unless defined?(#counter)
puts "Stepping through #{scenario.title}"
#counter = 0
end
#counter += 1
print "At step ##{#counter} of #{scenario.steps.count}. Press Return to"\
' execute...'
STDIN.getc
end

Cucumber: Before hook run only once for all scenarios

I have a scenario outline with multiple scenarios. I'd like my Before hook to run only once so I can bootstrap the ActiveRecord objects I need to run against all of the scenarios. The problem is if I use
Before do
# my code here
end
This will execute before each Scenario. Is there anyway to run it once for the entire Outline?
I think if you simply create the objects in a file in features/support they will be persisted:
ImportantThing.create(:name => "USEFUL THING")
This is because before every Scenario Cucumber will start a database transaction and then rollback to its prior status, which should contain the objects you've loaded.
I had the same problem, where I needed to create a subscriber manager once for all of my event logging tests. If I just used a before hook or a regular step (e.g. a Given), the manager would be created before each scenario.
My solution was ultimately to use a tagged before hook on my first scenario.
Before('#first_logging_scenario') do
# do something useful
end
To shutdown my manager, I used a tagged After hook with my last scenario
After('#last_logging_scenario') do
# do something useful
end

How to skip certain tests with Test::Unit

In one of my projects I need to collaborate with several backend systems. Some of them somewhat lacks in documentation, and partly therefore I have some test code that interact with some test servers just to see everything works as expected. However, accessing these servers is quite slow, and therefore I do not want to run these tests every time I run my test suite.
My question is how to deal with a situation where you want to skip certain tests. Currently I use an environment variable 'BACKEND_TEST' and a conditional statement which checks if the variable is set for each test I would like to skip. But sometimes I would like to skip all tests in a test file without having to add an extra row to the beginning of each test.
The tests which have to interact with the test servers are not many, as I use flexmock in other situations. However, you can't mock yourself away from reality.
As you can see from this question's title, I'm using Test::Unit. Additionally, if it makes any difference, the project is a Rails project.
The features referred to in the previous answer include the omit() method and omit_if()
def test_omission
omit('Reason')
# Not reached here
end
And
def test_omission
omit_if("".empty?)
# Not reached here
end
From: http://test-unit.rubyforge.org/test-unit/en/Test/Unit/TestCaseOmissionSupport.html#omit-instance_method
New Features Of Test Unit 2.x suggests that test-unit 2.x (the gem version, not the ruby 1.8 standard library) allows you to omit tests.
I was confused by the following, which still raises an error to the console:
def test_omission
omit('Reason')
# Not reached here
end
You can avoid that by wrapping the code to skip in a block passed to omit:
def test_omission
omit 'Reason' do
# Not reached here
end
end
That actually skips the test as expected, and outputs "Omission: Test Reason" to the console. It's unfortunate that you have to indent existing code to make this work, and I'd be happy to learn of a better way to do it, but this works.

Resources