Could anyone give me a good use case to illustrate the differences between Test::Unit::TestCase#cleanup and Test::Unit::TestCase#teardown?
Thx
From the documentation:
cleanup is called after every test method runs but the test method isn't marked as 'passed'.
teardown is called after every test method runs. (Regardless of whether or not the test passed.)
Related
I am testing a class that makes use of a client that makes external requests and I would like to mock this client, but verify that it gets called, however I am getting a double error.
My test looks like something like this:
describe '#execute' do
let(:attributes) { {foo: 'bar'} }
let(:client_double) { double('client', create: nil) }
let(:use_case) { described.class.new }
before do
allow(Client::Base).to receive(:new).and_return(client_double)
use_case.execute(attributes)
end
it 'creates something' do
expect(Something.find_by(foo: 'bar')).not_to be_nil
end
it 'calls client' do
expect(client).to have_received(:create).with('bar')
end
end
and the first example passes as expected, however rspec keeps breaking in the second example giving me this error:
#<Double "foo"> was originally created in one example but has leaked into another example and can no longer be used. rspec-mocks' doubles are designed to only last for one example, and you need to create a new one in each example you wish to use it for.
someone knows what I can do to fix it?
Reusing Fixtures with Let Methods
In this case, before is actually before(:each), which is reusing the client_double and attributes you defined with the #let helper method. The let commands make those variables functionally equivalent to instance variables within the scope of the described object, so you aren't really testing freshly-created objects in each example.
Some alternatives include:
Refactor to place all your setup into before(:each) without the let statements.
Make your tests DAMP by doing more setup within each example.
Set up new scope for a new #describe, so your test doubles/values aren't being reused.
Use your :before, :after, or :around blocks to reset state between tests, if needed.
Since you don't show the actual class or real code under test, it's hard to offer specific insights into the right way to test the object you're trying to test. It's not even clear why you feel you need to test the collaborator object within a unit test, so you might want to give some thought to that as well.
It turns out I was using a singleton as a client and haven't realized before, so it was trully class caching it through examples. To fix it all I did was mock the instantiate method instead of the new method and everything worked.
So in the end this worked:
allow(Client::Base).to receive(:instantiate).and_return(client_double)
I'm writing a test in MiniTest to the app which uses Devise and I have a little (I hope) problem.
I want to check if the user's password is correct. There is a method
valid_password?(password) called on a particular user which does what I need.
But my problem is that in this app this method is overwritten in that way:
def valid_password?(password)
if condition
# some else code
else
super
end
end
Is there any possibility to use valid_password? from super (Devise) in the unit tests?
Thanks in advance for any help.
There are some "hacky" ways that you could achieve this, but the rightâ„¢ way to do this is to structure your test such that condition is falsey. The way to do this, of course, depends on how condition is defined!
For example, suppose the method is implemented as:
def condition(password)
password.length < 10
end
In that case, you should simply run the test with a long password.
You could also (as a last resort) stub the condition method to return false - but this is bad practice. Your test would then not be a reflection of reality, since the actual circumstances under which super is being executed may not be fulfilled.
I am working through Learn Ruby The Hard Way and came across something intriguing in exercise 49.
In parser.rb I have a function named skip(word_list, word_type) at the top level, which is used to skip through unrequited words (such as stop words) in user input. It is not encapsulated in a class or module. As per the exercise I have to write a unit test for the parser.
This is my code for the Unit Tests:
require "./lib/ex48/parser"
require "minitest/autorun"
class TestGame < Minitest::Test
def test_skip()
word_list = [['stop', 'from'], ['stop', 'the'], ['noun', 'west']]
assert_equal(skip(word_list, 'stop'), nil)
assert_equal(skip([['noun', 'bear'], ['verb', 'eat'], ['noun', 'honey']], 'noun'), nil)
end
end
However, when I run rake test TESTOPTS="-v" from the command line, these particular tests are skipped. This seems to be because there is a clash with the skip method in the Minitest module because they run perfectly after I change the name to skip_words.
Can someone please explain what is going on here exactly?
"Top level functions" are actually methods too, in particular they are private instance methods on Object (there's some funkiness around the main object but that's not important here)
However minitest's Test class also has a skip method and since the individual tests are instance methods on a subclass of Test you end up calling that skip instead.
There's not a very simple way of dealing with this - unlike some languages there is no easy way of saying that you want to call a particular superclass' implementation of something
Other than renaming your method, you'll have to pick an alternative way of calling it eg:
Object.new.send(:skip, list, type)
Object.instance_method(:skip).bind(self).call(list, type)
Of course you can wrap this in a helper method for your test or even redefine skip for this particular Test subclass (although that might lead to some head scratching the day someone tries to call minitest's skip.
Jasmine's beforeEach/ afterEach method runs for each spec defined. Is there a way to run a method once for a group of tests? I am not looking for a solution to use a variable to track if a a method was run or not. It makes teardown tricky.
Edit:
Removing jasmine as it already have the beforeAll and afterAll methods. Protractor does not have it yet (https://github.com/angular/protractor/issues/103).
The workaround #jmr suggested is to use a setup and a teardown spec ( it("should setup"...) ).
I'm new to BDD, and I'm finding alot of instances where I'm adding instance variables to attr_accessor only so that my tests have an easy way to validate whether they are in the state that they should be in. But this feels a little dirty because no other class needs this information, and so I'm only making it public for the tests. Is this standard or a sign of bad design?
For example I have a collection class which stores an object, and then commits it to a batch array. At the end of the import, the batch array is used to make a batch insert into the database. But there is no need to check on the state of the batch at any point. But in testing I'm wanting to make sure that the batch is in the state that I think it is, and so am opening up that variable for inspection. Is the fact that it's not being checked within the code the real problem?
Is using instance_variable_get an option for you?
>> class Foo
.. def initialize
.. #foo = 'bar'
.. end
.. end #=> nil
>> Foo.new.instance_variable_get(:#foo) #=> "bar"
DON'T Do That!
This is going too deep. See the comments from #Andy and #Michael in the thread on the other 'accepted' answer
Don't write unit tests that look inside the code unit. If it's not something you can see from the external interfaces to the object then it doesn't need to be unit tested. You are going past how the code behaves into how it implements that behavior, and you don't want tests that go down to that level as they don't provide any real value in terms of proving that the code does what it should.
Just consider how many tests you might have to update if someone re-factors that code and in order to make it more readable changes the internal names of things.. or maybe finds a better way of doing whatever and all the instance variables get altered.. The code unit could still be working perfectly fine, but the unit tests would fail..
Alternatively if a change was made that adjusts how the internal variables report out to the interface, the code could effectively be broken, but the tests that are looking at the internal values of the instance variables would not report any failure.