Introspection during Rails Test Execution -- How? - ruby-on-rails

I am generating some output files during the execution of rails tests, and I would like to be able to name the files based on the current test class and current test method. Is there a way to get this information built into Test::Unit? Is there some clever way to get this from inside the test methods? I can get the current method name by calling method, but I can't figure out how to get the current class name.
Calling self.class returns Controller, not the actual test class ( PostTest, for example ).

This should return your class name in unit test:
test "class name" do
puts "#{self.class.name}"
end
Are you saying this is not working for you? It should work.

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.

How does assigns know where to look for the instance variable in integration tests?

I've been following a rails tutorial and got to know the assigns method of Rspec.
This is how it's being used in an integration test:
class SomeTest < ActionDispatch::IntegrationTest
test "simplified test" do
get '/some/path'
#some assertions
get '/other/path'
assert_equal 'changed', assigns(:some_variable)
end
end
Assigns seem to access the controller/view of the last call.
Is that so? how does assigns get to the instance variable some_variable?
It seems to imply there is some state being preserved in the integration test that is accessed from assigns.
It turned out that Rails treat Integration tests pretty much like functional ones, so the instance variables described in the documentation for the latter works in the former. In integration tests these variables tend to be overwritten, so you'll access the state prior to your call.
That means that in an integration test you may access:
#controller: the last controller being invoked
#request: the last request sent
#response: the last response object returned
assings just wraps the access to #controller.view_assigns where all the instance variables that will be available for the view are held.

How to get the value of a Controller variable in rails console

I set a variable inside a Controller and I'm trying to just do something as simple as read that variable in the rails console.
I thought about just doing #test in the console which is the name of the variable. but it shows as >null. When I do puts under where I set the variable it traces out the correct value in my terminal window.
Any ideas what I need to do to get to this variable via the console.
I tried putting the name of the controller first and then .variable but that threw an error
I can see what's inside my models by just using the model name and some attributes like .first and .last
You'd have to instantiate the controller and provide a public accessor to get the value in rails console.
If you're trying to debug something, I recommend you check out Pry. It's a Ruby debugging REPL. Do a require 'pry' in your controller, and put binding.pry somewhere in an action, when you execute that controller method--either interactively in a browser, or via a functional test (I recommend the latter)--it will open the Pry REPL and #test will be in scope there.
Check out this Railscast for some help using it.
Alternately, just rely on good unit or functional testing. Write a test around the method and add an assertion on assigns(:#test) to compare the value to your expectation. Check out the RSpec controller spec documentation.

Is it possible to use a method in a Unit Test file in Rails Console?

I have a unit test method in my test/unit/model_test.rb :
def valid_sendRequestXML(account)
Hpricot.XML <<-XML
<ticket>#{account.api_token}</ticket>
XML
end
And I'm trying to manually run some things in my console to see what is failing where. Is it possible to somehow call this method within console? If so, how?
You can require unit test files just like any other Ruby file. The unit tests are methods of a class, so you can instantiate the testcase and run the methods you'd wish to run.
Also consider using pry. Just put binding.pry in your unit test, run it will open a console for you to inspect all the local variables (and other stuff) in.

Helper functions in Rails unit tests

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.

Resources