Helper functions in Rails unit tests - ruby-on-rails

I'm using this sort of code in my code in my Unit tests.
test "should be awesome" do
assert true
end
I'm using FactoryGirl instead of fixtures.
I find that I'm repeating myself a lot and having helper functions would be quite useful. What's the best way to create and call a helper function in the unit test? Is there a before_filter available like it is in the controllers (I tried putting it in, but it's just an undefined method). Any help is appreciated!

You can add utility functions to your unit tests without a problem. As long as you don't call them name them like "test_something" they won't get run as unit tests. You can then call them from your actual unit test methods (the format you use boils down to having a method in the class anyway).
So:
test "should be awesome" do
assert_general_awesomeness
assert true
end
private
def assert_general_awesomeness
assert true
end
Utility methods that are going to be used all over the place can go in test_helper and they will be available to all your tests. You could alternatively have a module that you mix in to your tests to provide common utility methods.
If you are doing common calls to set up before a unit test you can put in in a setup method which will be called before each test in the class.

Related

how do I test a private method on controller, using minitest?

Very new to testing
I have a model-less rails app with a controller called "PokerController"
in poker_controller.rb, I have a private method that looks like this:
private
def test(x)
1 + x
end
Then I have a file called 'poker_controller_test.rb' in test/controllers
I'm trying to do something like this:
require 'test_helper'
class PokerControllerTest < ActionController::TestCase
test "check if test == 2" do
test = test(1)
assert test == 2
end
end
As you can see, I'm trying to save the result of the function 'test' being called, to a variable called 'test' then I'm checking to see if that == 2.
Basically, I'm trying to pass in a number (in this case '1') to the test method, and I want the test to add 1 to 1, and expect to get 2.
I'm sure I'm just not setting up the test right, but how do I call a custom method like this and then evaluate what's returned?
Here's my result from the error in the test:
Error:
PokerControllerTest#test_check_if_test_==_2:
ArgumentError: unknown command "\x01"
test/controllers/poker_controller_test.rb:6:in `test'
test/controllers/poker_controller_test.rb:6:in `block in <class:PokerControllerTest>'
You don't.
Testing private methods in general is frowned upon*.
In Rails you mainly test controllers through integration tests. These are tests that send real HTTP requests to your application and then you write assertions about the response or the side effects of sending the request.
"[...] You can test what cookies are set, what HTTP code is returned, how the view looks, or what mutations happened to the DB, but testing the innards of the controller is just not a good idea."
- David Heinemeier Hansson
An example of an integration test is:
require "test_helper"
class PokerControllerTest < ActionDispatch::IntegrationTest
test "can see the welcome page" do
get "/path/to/somewhere"
assert_select "h1", "Welcome to my awesome poker app"
end
end
If you have a method that you want to test in isolation it does not belong in your controller in the first place and arguably it should not be a private method either.
You should test the public API of your objects. The public API of a controller is the methods that respond to HTTP requests via the router.
The use of ActionController::TestCase is discouraged outside of legacy applications.
New Rails applications no longer generate functional style controller
tests and they should only be used for backward compatibility.
Integration style controller tests perform actual requests, whereas
functional style controller tests merely simulate a request. Besides,
integration tests are as fast as functional tests and provide lot of
helpers such as as, parsed_body for effective testing of controller
actions including even API endpoints.
Besides that the issues with your test is that you're calling the test method on the instance of ActionController::TestCase and not your controller. You're then shadowing the method by defining an instance variable with the same name which is rarely a good thing.
Even if you did call the method on the controller Ruby would still raise an error since you're calling a private method from outside the object - thats the whole point of private methods.
While you could violate encapsulation by calling #controller.send(:test) this is just a bad idea on so many levels.

Rails, Is there a way to generate Unit Tests from Existing Controllers and methods defined in them?

I was wondering if there is a script that can take existing codebase and generate unit tests for each method in controllers. By default all would be passing since they would be empty and i can remove tests i for methods i dont feel important.
This would save huge time and increase testing. Since i'd have to define only what each method should output and not boilerplate that needs to be written.
You really shouldn't be doing this. Creating pointless tests is technical debt that you don't want. Take some time, go through each controller and write a test (or preferably a few) for each method. You'll thank yourself in the long run.
You can then also use test coverage tools to see which bits still need testing.
You can use shared tests to avoid repetition. So for example with rspec, you could add the following to your spec_helper/rails_helper
def should_be_ok(action)
it "should respond with ok" do
get action.to_sym
expect(response).to be_success
end
end
Then in your controller_spec
describe UserController do
should_be_ok(:index)
should_be_ok(:new)
end

Test Redcarpet Markdown helper

I have a markdown helper that looks like this in application_helper.rb.
How would you go about writing a test for something like this? Also, is this the best way to generate simple HTML from markdown?
Thanks!
def markdown(text)
Redcarpet::Markdown.new(Redcarpet::Render::HTML, :autolink => true, :space_after_headers => true).render(text).html_safe
end
Two options come to mind:
Stub out Redcarpet::Markdown and create an expectation of what it should receive:
expect(Redcarpet::Markdown).to receive(:new).with(...) # `with` args omitted for brevity
markdown(text)
The problem here is that the coupling between the method and the test is very high. It's very difficult to refactor the method without breaking the test, even though the method actually functions the same.
Assert the correctness of the output text directly:
expect(markdown(text)).to eq 'This is markdownified'
This allows you to refactor better, but it seems more like an integration test, not a unit test, and is almost testing Redcarpet more than your own method. Unit tests should usually assume that the external methods they call work correctly.
This is one of those cases where testing feels redundant to me since the method is just a thin wrapper around another, and I would not be against not unit testing it, and rather ensuring that you have an integration test—if this is by having your spec be an integration test, then that's probably okay.
It's ultimately all up to you and your TDD workflow and overall testing principles though.

Where to put common Unit Test code in ruby on rails environment?

Using Rails 3.0, I have a small bit of code that I seem to be calling in all my Unit tests.
Is there a common place to put shared unit test code that won't be incorporated into both unit and functional tests? I'd rather ONLY incorporate it into the needed files, just the unit tests.
I'm new to testing practices in general. Is it common in Rails to test validations (for example, test: validates_presence_of :name)? Most of my functions that test validations on a model are all basically the same (just swap in and out correct fixture and attribute name). Doesn't seem very DRY. Looking for a way to refactor.
Thanks.
You can place the code in the test/test_helper.rb file.
You should already find a code fragment that looks like this
class ActiveSupport::TestCase
self.use_transactional_fixtures = true
self.use_instantiated_fixtures = false
end
If the code should be used in all your tests, you can add your methods in the ActiveSupport::TestCase class. Otherwise, wrap them into a Module and mix the module where required.
It's a good practice to test validations not to test the validation itself (the validates_presence_of macro is already tested in the Rails codebase), but to make sure chances in your code don't affect your class business.
For instance, there might be validation which needs to be triggered only in specific events. Or you might want to make sure no one removed your super-secret validation on that specific model.
If you want to test your model validations, I encourage you to check out shoulda. Shoulda provides several handy methods to test your validations.
class PostTest < ActiveSupport::TestCase
should belong_to(:user)
should validates_presence_of(:id)
end

Where should I place universal setup code for rails unit tests?

I would like to stub a web service proxy before all my unit tests. I could call some shared code in each unit test, but I was wondering if there is a better way.
I am using Shoulda.
Thanks
in test/test_helper you can do the following:
class ActiveSupport::TestCase
def stub_some_stuff
…
end
setup :stub_some_stuff
end
Be careful to ensure you don't just do it once by putting it outside of a setup block, doing so may result in the stub being torn down by the first test, and then all future requests just go straight through!
test/test_helper is a good place for common code - this will be injected into your TestCases

Resources