Rspec and prevent tests from being run under some circumstances - ruby

I use rspec like this:
describe
it 'should check if the xx':
end
How do I prevent some tests in the it end body from being run if some condition is met? For example, if the function is_disabled returns true then the following tests should not run:
it 'should check if the xx1':
end
it 'should check if the xx2':
end
but the following should:
it 'should check if the xx3':
end
it 'should check if the xx4':
end
can you do :
context "if api calls enabled for MC, #app.is_disabled => 'USD' do
it 'should check if the xx3':
end
it 'should check if the xx4':
end
end

Yes, you can use rspec implicit filters. Example:
describe "if the app is enabled", :unless => #app.is_disabled do
it 'should check if the xx3':
end
it 'should check if the xx4':
end
end
describe "if the app is disabled", :if => #app.is_disabled do
it 'should check if the xx1':
end
it 'should check if the xx2':
end
end

Related

Skip multiple examples in RSpec?

Does anyone know a way to skip multiple examples within a group, without duplicating the skip statement between them?
For example, given this test:
describe 'some feature' do
it 'should do something' do
...
end
it 'should do something else too' do
...
end
end
a skip doesn't work if placed before the first example, like so:
describe 'some feature' do
skip 'I would like to skip both with one statement'
it 'should do something' do
...
end
it 'should do something else too' do
...
end
end
An ideal solution would allow me to skip at any level of the example structure (describe/feature, context, and scenario/it) and would skip all children of that level of the hierarchy.
In other words, would allow me to do:
describe 'some feature' do
it 'should do something' do
...
end
it 'should do something else too' do
skip 'just one of these for now'
...
end
end
AND
describe 'some feature' do
skip 'everything within this describe block'
it 'should do something' do
...
end
it 'should do something else too' do
...
end
end
AS WELL AS
describe 'some feature' do
context 'such and such' do
skip 'just this context'
it 'should do something' do
...
end
it 'should do something else too' do
...
end
it 'but do not skip this one' do
...
end
end
As described in the documentation, you can use metadata to skip a context.
describe 'some feature', :skip do
it 'should do something' do
# This example is skipped
end
it 'should do something else too' do
# This example is skipped as well
end
end

Run after block after specific test in Rspec

Is there a way I can run the after/before block after/before a specific test using labels?
I have 3 it blocks
describe "describe" do
it "test1" do
end
it "test2" do
end
after(<<what goes here??>>) do
end
end
How do I run the after block only after test2? Is that possible?
You should use contexts to do this. Something like:
describe "describe" do
context 'logged in' do
before(:each) do
# thing that happens in logged in context
end
after(:each) do
# thing that happens in logged in context
end
it "test1" do
end
end
context 'not logged in' do
# No before/after hooks here. Just beautiful test isolation
it "test2" do
end
end
end
Having if/else conditions in before/after blocks is a code smell. Don't do it that way. It'll only make your tests brittle, error prone, and hard to change.
The best way to do this is just use a context. For your example:
describe "AutomateFr33k's fr33ky tests" do
it "runs test1" do
expect(true).to be_true
end
context "do something afterwards" do
after { puts "running something after test2!" }
it "runs test2" do
expect(5).not_to eq(4)
end
end
end
Yes you can do that, have a look here
You can achieve that using metadata in rspec
RSpec.configure do |config|
config.treat_symbols_as_metadata_keys_with_true_values = true
end
describe "Skip hook demo" do
# If prior to RSpec 2.99.0.beta1
after do
puts "before hook" unless example.metadata[:skip]
end
# If RSpec 2.99.0.beta1 or later
after do |example|
puts "before hook" unless example.metadata[:skip]
end
it "will use before hook" do
end
it "will not use before hook", :skip do
end
end

Run cleanup step if any it block failed

When one of my it blocks fails, I want to run a cleanup step. When all of the it blocks succeed I don't want to run the cleanup step.
RSpec.describe 'my describe' do
it 'first it' do
logic_that_might_fail
end
it 'second it' do
logic_that_might_fail
end
after(:all) do
cleanup_logic if ONE_OF_THE_ITS_FAILED
end
end
How do I implement ONE_OF_THE_ITS_FAILED?
Not sure if RSpec provides something out of the box, but this would work:
RSpec.describe 'my describe' do
before(:all) do
#exceptions = []
end
after(:each) do |example|
#exceptions << example.exception
end
after(:all) do |a|
cleanup_logic if #exceptions.any?
end
# ...
end
I digged a little into the RSpec Code and found a way to monkey patch the RSpec Reporter class. Put this into your spec_helper.rb:
class RSpecHook
class << self
attr_accessor :hooked
end
def example_failed(example)
# Code goes here
end
end
module FailureDetection
def register_listener(listener, *notifications)
super
return if ::RSpecHook.hooked
#listeners[:example_failed] << ::RSpecHook.new
::RSpecHook.hooked = true
end
end
RSpec::Core::Reporter.prepend FailureDetection
Of course it gets a little more complex if you wish to execute different callbacks depending on the spec you're running at the moment.
Anyway, this way you do not have to mess up your testing code with exceptions or counters to detect failures.

How to ignore or skip a test method using RSpec?

please guide how to disable one of the below test methods using RSpec. I am using Selenuim WebDriver + RSpec combinations to run tests.
require 'rspec'
require 'selenium-webdriver'
describe 'Automation System' do
before(:each) do
###
end
after(:each) do
#driver.quit
end
it 'Test01' do
#positive test case
end
it 'Test02' do
#negative test case
end
end
You can use pending() or change it to xit or wrap assert in pending block for wait implementation:
describe 'Automation System' do
# some code here
it 'Test01' do
pending("is implemented but waiting")
end
it 'Test02' do
# or without message
pending
end
pending do
"string".reverse.should == "gnirts"
end
xit 'Test03' do
true.should be(true)
end
end
Another way to skip tests:
# feature test
scenario 'having js driver enabled', skip: true do
expect(page).to have_content 'a very slow test'
end
# controller spec
it 'renders a view very slow', skip: true do
expect(response).to be_very_slow
end
source: rspec 3.4 documentation
Here is an alternate solution to ignore (skip) the above test method (say, Test01) from sample script.
describe 'Automation System' do
# some code here
it 'Test01' do
skip "is skipped" do
###CODE###
end
end
it 'Test02' do
###CODE###
end
end
Pending and skip are nice but I've always used this for larger describe/context blocks that I needed to ignore/skip.
describe Foo do
describe '#bar' do
it 'should do something' do
...
end
it 'should do something else' do
...
end
end
end if false
There are a number of alternatives for this. Mainly marking it as pending or skipped and there is a subtle difference between them. From the docs
An example can either be marked as skipped, in which is it not executed, or pending in which it is executed but failure will not cause a failure of the entire suite.
Refer the docs here:
https://relishapp.com/rspec/rspec-core/v/3-4/docs/pending-and-skipped-examples/pending-examples
https://relishapp.com/rspec/rspec-core/v/3-4/docs/pending-and-skipped-examples/skip-examples
There are two ways to skip a specific block of code from being running while testing.
Example : Using xit in place of it.
it "redirects to the index page on success" do
visit "/events"
end
Change the above block of code to below.
xit "redirects to the index page on success" do #Adding x before it will skip this test.
visit "/event"
end
Second way: By calling pending inside the block.
Example:
it "should redirects to the index page on success" do
pending #this will be skipped
visit "/events"
end

Testing with Rspec - The correct way

My weakest point when it comes to coding, is using TDD & BDD methods - I tend to just write code.. but it is something that I am trying to work on.
Could anyone point out the best way to go about the following problem:
Class1:
module TempMod
class MyClass
def initalize(config)
#config = config
end
def process(xml)
if react_upon? xml.something
puts 'yeah'
else
puts 'nah'
end
end
def react_upon?(xml_code)
#code here
end
end
end
So lets say I wanted to test this class, or build it from a TDD point of view so I write my tests:
describe TempMod::MyClass do
let(:config) {double}
let(:myclass) {TempMod::MyClass.new config}
context 'Given that the xml is something we react upon' do
it 'should check that it is valid' do
myclass.process '<some><xml>here</xml></some>'
end
it 'should output yea'
end
end
How do I test that it is calling the react_upon? method. Do I even want to see it is calling it?
Is the proper way to test it, to test all the functions like the react_upon? itself independently of the other functions?
This is properly the main thing that is most confusing me with this sort of testing. Am I testing the whole class, or just individually testing the functions, and not their interactions with the other functions in that class?
Also I realize the the react_upon? might not adhere to the Single responsibility principle and I would probably move that out to its own module/class which I could test using a stub.
If anyone can shed some light on this for me that would be awesome.
edit:
describe TempMod::MyClass do
let (:valid_planning_status_xml) {
'<StatusUpdate> <TitleId>2329</TitleId> <FromStatus>Proposed</FromStatus> <ToStatus>Confirmed</ToStatus> </StatusUpdate>'
}
let(:config) { double }
let(:status_resolver) { double }
subject(:message_processor) { TempMod::MyClass.new config, status_resolver }
context 'Given that the message XML is valid' do
it 'should check the context of the message' do
expect(message_processor.process valid_planning_status_xml).to call :check_me
end
context 'Given that the message is for a planning event update' do
it 'should call something' do
pending
end
end
context 'Given that the message is for a recording job update' do
end
context 'Given that the message is for a video title update' do
end
end
end
Your question confused me a bit is this what you are asking
module TempMod
class MyClass
def initalize(config)
#config = config
end
def process(xml)
react_upon?(xml.something) ? 'yeah' : 'nah'
end
def react_upon?(xml_code)
#code here
end
end
end
Then test like
describe TempMod::MyClass do
let(:config) {double}
let(:myclass) {TempMod::MyClass.new config}
context 'Given that the xml is something we react upon' do
it "should respond to react_upon?" do
expect(myclass).to respond_to(:react_upon?)
end
it "should react_upon? valid xml" do
expect(myclass.react_upon?(YOUR VALID REACTION GOES HERE)).to be_true
end
it "should not react_upon? invalid xml" do
expect(myclass.react_upon?(YOUR INVALID REACTION GOES HERE)).to be_false
end
it "should say 'yeah' if it is valid" do
expect(myclass.process('<some><xml>here</xml></some>')).to eq('yeah')
end
it "should say 'nah' if it is invalid" do
expect(myclass.process('<some><xml>here</some>')).to eq('nah')
end
it 'should check the context of the message' do
expect(myclass).to receive(:react_upon?).with('<some><xml>here</xml></some>')
myclass.process('<some><xml>here</xml></some>')
end
end
end
Right now your tests have no expectations so I added one that expects myclass to respiond_to the react_upon? method and another that expects myclass.process(xml) to respond with a String that equals yeah.

Resources