How to test Capybara? - ruby

I have a script that use Capybara to publish links in Google+. I would like to have tests to cover this functionality. Usually Capybara is using as a tool for writing Integration tests. In may case i need to test Capybara itself.
I see 3 possible ways:
stub capybara's method (but in this case i test nothing but just stubbed methods)
test capybara agains saved HTML/JS page (that will help me understand that i did not break anything during refactoring)
do not test at all (no comments here)
Have you ever faced such a problem?

If you register different drivers for your app and your test code, possibly manage the sessions manually depending on how you're using it in your app, and make sure you're careful with Capybaras setting's you should be able to go with option 2. You have to be careful with Capybaras settings because most of them are global so changing them for your tests will also change them for your app.

Related

Changing the base URL for Capybara Acceptance Tests

I am developing a sinatra based web application and I extensively use tests to make sure that everything is working before deployment. As testing frameworks I use minitest::specs and capybara with webkit.
My problem is that after deployment my application runs with a base url like this:
http://cool.server.net/to-the-application/
But during tests capybara assumes a clean base-url with a path to / not to to-the-application/. This means I can't test to find bugs which relate to forgetting to set the base-url within links and actions.
For dry testing I followed Changing the base URL for Rails 3 development and modified my config.ru, but I haven't found any way to get capybara to use a different base.
Any ideas how to solve this?
If using the rack_test driver the hostname is completely ignored so changing it isn't going to do anything. If using a different driver you can specify
Capybara.app_host = "http://cool.server.net"
Note that cool.server.net would generally need to resolve to 127.0.0.1 since thats where Capybara binds the app being tested.
Update: After thinking about this I'm not sure that is what you wanted. If what you want is for Capybara to mount your app under /to-the-application then you're going to have to create your own app object which you assign to Capybara.app - see https://github.com/teamcapybara/capybara/blob/2.13_stable/lib/capybara/rails.rb#L4 for how Capybara currently mounts the app.

Difference between scraping and testing mode in CasperJS

I'm absolutely new to CasperJS and I'm wondering what's the difference between those 'two modes'.
Both access the DOM, it seems that test mode has a limited access and functionality.
I looked for this question around and didn't find the answer.
In test mode you have access to the tester module and with it access to asserts, test suites and (xml) reports. This is not accessible in plain mode anymore (earlier versions than 1.1-beta4 had access to some of the test mode stuff in plain mode).
The only drawback to test mode is that you can only have one casper instance which is injected. This leads to:
When you try to create it, you will get an error.
(Nearly) all options have to be assigned directly and cannot be passed to create as an object.
Some things cannot be done like this one: A: How to open a new tab in CasperJS

Rails rspec controller test vs integration test

I just completed writing a detailed rspec capybara integration and unit tests for Rails app, which includes mocking Omniauth (twitter) login, filling in forms, data validations, etc. However, I am wondering whether there is a need to write a separate controller or functional test.
Would appreciate your input and any links to further readings etc.
I'll play devil's advocate here, since I know I'm probably in the minority with this opinion: I actually prefer to do exceedingly thorough controller testing. A few reasons:
1) I find it easier to systematically test every path and outcome at the controller level than at the integration test level. My integration tests are primarily just happy-paths, and some of the more common error paths.
2) A lot of potential security issues occur at the controller level. Thorough testing helps me ensure that nothing malicious can get through to my model logic.
3) This is subjective, but it really forces me to think about some of the long-tail paths that my application might go through. What if someone tries to for an invalid password reset token into the URL? Controller testing ensures that I consider all options.
4) Unlike integration tests, they're fairly straight-forward to test. Each action is just a ruby method!
Personally, I think if your request (integration) spec is exercising all code paths you're covered. Ryan Bates has a great Railscast about how he tests here: http://railscasts.com/episodes/275-how-i-test?autoplay=true and about 5:05 in he says a similar thing. Like you I like to write integration tests rather than controller specs. Most of the time controllers simply front CRUD type operations anyway (especially if you're careful about keeping domain logic out of the controller), so all you're testing is the scaffolding.

How to run cucumber scenario with and without javascript avoiding code duplication

I was wondering if there is any way to run cucumber scenario with and without javascript without duplicating code.
I develop website that utilizes html5 navigation. However it should work find if browser doesn't support html5 features.
I would like to write cucumber test that would test navigation.
I know I can test basic html navigation with simple cucumber scenario. And I can test html5 navigation with same scenario but with #javascript tag.
I would really love to avoid this code duplication.
I was experimenting with around hooks, hoping that I could simple call block, then call same block with
Capybara.using_driver(Capybara.javascript_driver) { block.call }
However this doesn't work.
Anyone have any idea how to implement this?
P.S.
I'm quite new to Ruby, and just started working with cucumber.
It looks like you need two different scenarios. I'd use the Background feature to avoid step definitions but it's a matter of taste.
Based on the solution by Jon M of using the environment variable, you need to set the current_driver before each scenario runs (which seems better than changing the default_driver).
Before do
if ENV['USE_JS_DRIVER']
Capybara.current_driver = Capybara.javascript_driver
end
end
And then running
cucumber .
USE_JS_DRIVER=1 cucumber .
If you don't want to create separate features to deal with both types of browser, then one solution is to use an environment variable to tell cucumber which type of browser driver to use, and invoke cucumber twice.
You'd need to query the environment variable to set the correct driver, probably in env.rb:
if ENV['USE_JS_DRIVER']
Capybara.current_driver = Capybara.javascript_driver
end
And then you could run either/both of:
cucumber .
USE_JS_DRIVER=1 cucumber .
You'd have to find some useful way of merging the results from both cucumber runs, but depending on your needs this could be a simpler solution than duplicating your scenarios.

How do you figure out what test will best represent the feature you want to create?

Test driven development on wikipedia says first develop a test that will fail because the feature does not exist. Then build the code to pass the test. What does this test look like?
How do you figure out what test will best represent the feature you want to create?
Can someone give an example?
Like if I make a logout button feature to a web application then would the test be hitting the page looking for the button? or what?
I heard test driven is nice for regression testing, I just don't know how to start integrating it with my work.
Well obviously there are areas that are more suited for TDD than others, and running frontend development is one of the areas that I find difficult to do TDD on. But you can.
You can use WATIN or WebAii to do that kind of test. You could then:
Write a test that checks if a button exists on the page ... fail it, then implement it, and pass
Write a test that clicks the button, and checks for something to change on the frontend, fail it, implement feature and pass the test.
But normally you would test the logic behind the actions that you do. You would test the logout functionality on your authenticationservice, that is called by your eventhandler in webforms, or the controller actions in MVC.
What does this test look like?
A test has 3 parts.
it sets up a context
it performs an action
it makes an assertion that the action did what it was supposed to do
How do you figure out what test will best represent the feature you want to create?
Tests are not based on features (unless you are talking about a high level framework like cucumber), they are based on "units" of code. Typically a unit is a function, and you will write multiple tests to assert all possible behaviors of that function are working correctly.
Can someone give an example?
It really varies based on the framework you use. Personally, my favorite is shoulda, which is an extension to the ruby Test::Unit framework
Here is a shoulda example from the readme. In the case of a BDD framework like this, contextual setup happens in its own block
class UserTest < Test::Unit::TestCase
context "A User instance" do
setup do
#user = User.find(:first)
end
should "return its full name" do
assert_equal 'John Doe', #user.full_name
end
context "with a profile" do
setup do
#user.profile = Profile.find(:first)
end
should "return true when sent #has_profile?" do
assert #user.has_profile?
end
end
end
end
Like if I make a logout button feature to a web application then would the test be hitting the page looking for the button? or what?
There are 3 main types of tests.
First you have unit tests (which is what people usually assume you are talking about when you talk about TDD testing). A unit test tests a single unit of work and nothing else. This means that if your method usually hits a database, you make sure that it doesn't actually hit that database for the duration of the test (using a technique called "mocking").
Next, you have integration tests. An integration test usually involves interaction with the infrastructure, and are more "full stack" testing. So from your top level API, if you have an insert method, you would go through the full insert, and then test the resulting data in the database. Because there is more setup in these sorts of tests, they shouldn't really be run from developer machines (it is better to automate these on your build server)
Finally, you have UI testing. This is the most unreliable, and requires a UI scripting framework like Selenium or Waitr to automate clicking around your UI. Don't go crazy with this sort of testing, because these tests are notoriously fragile (a small change can break them), and they wont catch whole classes of issues anyways (like styling).
the unit test would be calling the logout function and verifying that the expected results occurred (user login record ended, for example)
clicking the logout button would be more like an acceptance test - which is also a good thing to do, and (in my opinion) well within the scope of TDD, but it tests TWO features: the button, and the resulting action
It depends on what platform you are using as to how your tests would appear. TDD is much harder in ASP.NET WebForms than ASP.NET MVC because it's very difficult to mock up the HTTP environment in WebForms to get the expected state of Session, Application, ViewState etc. as opposed to ASP.NET MVC.
A typical test is built around Arrange Act Assert.
// Arrange
... setup needed elements for this atomic test
// Act
... set values and/or call methods
// Assert
... test a single expected outcome
It's very difficult to give deeper examples unless you let us know the platform you plan to code with. Please give us more information.
Say I want to make a function that will add one to a number (really simple example).
First off, write a test that says f(10) == 11, then do one that says f(10) != 10. Then write a function that passes those tests. If you realise the function needs more capabilities, add more tests.
The test would be making sure that when the logout function was executed, the user was successfully logged out. Generally a unit testing framework such as NUnit or MSTest (for .Net stuff) would be used.
Web applications are notoriously hard to unit test because of all the contextual information generally required for the execution of server code on a web server. However, a typical example would mock up that information and call the logout logic, and then verify that the correct result was returned. A loose example is an MVC type test using NUnit and Moq:
[Test]
public void LogoutActionShouldLogTheUserOut()
{
var mockController = new Mock<HomeController>() { CallBase = true };
var result = mockController.Object.Logout() as ViewResult;
Assert.That(result.ViewName == "LogoutSuccess",
"Logout function did not return logout view!");
}
This is a loose example because really it's just testing that the "LogoutSuccess" view was returned, and not that any logout logic was executed. In a real test I would mock an HttpContext and ensure the session was cleared or whatever, but I just copied this ;)
Unit tests would not be testing that a UI element was properly wired up to an event handler. If you wanted to ensure that the whole application was working from top to bottom, this would be called integration testing, and you would use something besides unit tests for this. Tools such as Selenium are commonly used for web integration tests, whereas macro recording programs are often used for desktop applications.

Resources