As you probably know, just creating an app is not the last step before giving it to users. Before you decide to officially launch your Ruby on Rails app it's still worth checking it completely. For this purpose, it may be necessary to conduct functional tests, which will indicate which elements need to be refined. With our help, you'll learn how to properly execute all the tests to make your Rails application fully functional from a technical point of view and user-friendly at the same time.
What is the responsibility of the Rails test?
Prior to moving on to the various testing models, it will be necessary to complete the knowledge of the process itself. Testing a Rails application is relatively simple. It begins with the development of the test code skeleton, which is created when the models and controllers are created. Moreover, code refactoring does not affect the ability to validate the code. The Rails test can mirror browser behavior. This way, you can check the responsiveness of your application without having to do it through the browser.
What is the system testing in Rails?
System testing is nothing more than a thorough verification of the integrated software. Its purpose is to test Rails applications under conditions similar to user behavior. You might think, well, okay, but why using system tests when I can run the program manually after writing it and make any corrections manually? This approach may work, but in case you have a small application. At some point, your Rails project grows so large that you are not able to keep track of all the features. Then system testing becomes essential to avoid regression.
The mission of rails testing is to simulate as close as possible user behavior towards the application. As a result, the application, when implemented, is bug-free and doesn't cause any problems for users. With a dedicated test database, you can automate checking your tool every time.
Types of tests in Ruby on Rails
When testing framework Ruby on Rails, we are faced with 4 types of tests:
Unit testing is the most widely used automated testing method. Unit tests involve testing a piece of code based on a test method. After running the selected particular test method and setting certain parameters, it is checked whether the result of such a method matches the assumptions. A characteristic feature is that this type of testing is performed very quickly. That's why, for Rails applications such tests should be the most frequently performed.
Functional test is slightly more complicated than the unit test described earlier. The difference can be seen in the fact that there is more going on in each of these tests than in the unit tests. What's more, the role of functional testing is to check whether multiple components of the application are working properly.
Integration tests are responsible for checking applications from the outside. Their characteristic feature is the consideration of multiple controllers that are part of the user flow. Each integration test brings great value to the entire project, because it rests on the role of efficiency not of a part, but of the entire application.
Performance testing is designed to obtain a specific set of metrics with which actions can be made to improve the application code. Performance tests are also responsible for ensuring that users do not spend too much time waiting for a page to load. It's through them that you'll find out what's causing the application's speed and memory problems.
Concept of The Test Pyramid
Each of us has probably encountered more than once the concept of Maslow's hierarchy of needs presented in the form of a pyramid. A similar pyramid is present in testing Rails applications. However, in the test pyramid there are fewer floors. The model of the pyramid described above originated with Mike Cohn, who described the concept in his book "Succeeding with Agile".
Step 1: Unit tests
According to the author, the pyramid should illustrate the developer's chosen test suite. The basis in his considerations are unit tests. There should be many of them with a low level of sophistication. When creating unit tests, one should remember to avoid the most common mistakes. These include testing trivial code, tautological tests and tying the test suite to the implementation.
Step 2: Functional tests
The next floor of the pyramid should be rails functional tests for controllers. Essential at this stage, according to Cohn, are controller actions and validations, as well as their compatibility with the database. What should be tested are network request, user redirection, user authentication, presentation of relevant messages and information to the user.
Step 3: System tests
The pinnacle of the concept belongs to system testing. These are responsible for interacting with the application through the browser. As a result through system tests, the user flow can be simulated. Anything that requires the user to interact through a click and forms to fill out needs to be tested accordingly.
Types of testing framework tools (RSpec vs Capybara)
In Rails testing terminology, the most important thing is not the tools themselves but the testing principles. Nevertheless, it is useful to have knowledge of basic frameworks that facilitate the testing process. Among the most common framework tools are RSpec and Capybara.
RSpec is responsible for providing the appropriate structure for writing tests and the ability to run them. This is the most popular solution for commercial projects implemented in Rails testing code. In the case of Capybara, there is a library that uses Ruby to wrap the driver. This meets all the needs of simulating user keystrokes using convenient Ruby test methods.
What Do Rails tests look like in Railwaymen?
Testing is an essential part of developing the Ruby on Rails app at Railwaymen. Our base testing tool is RSpec, which we have been using in our work for many years. Our established requirement is 100% code coverage, so we insist among developers that they use the capabilities of this testing framework. In this way, we also reduce the additional cost for each new person joining the project.
Our default factory library is factory bot. We use it because it has a lot of capabilities and, used properly, provides the necessary performance. On the other hand, in terms of mocking & stubbing, there is nothing better for us than the elements assigned to RSpec. Thanks to the variety of cases that occur in this test framework, there is no need to add more libraries.
In Rails tests all external HTTP requests need to be disabled all the time. Every HTTP request must be stubbed either by stubbing the request itself or the methods that are responsible for executing it. However, when creating an integration with an external API, it is important to check that the code executes the correct requests with the correct parameters and headers. For this, we at Railwaymen use Webmock, which can easily block all requests in tests and provides a very simple DSL for stubbing and mocking. It also writes out all external HTTP requests along with information on how to mock it.
The test environment from our QA perspective
For the Quality Assurance team at Railwaymen, there are quite a few issues strictly related to testing Ruby on Rails applications. Of the manual types of tests listed above, functional tests and integration tests are the most common with us.
In addition, when testing the applications we create, we use the possibilities offered by API tests. In the course of building Rails API similarly, we use Test Driven Development, which significantly facilitates our work on the code.
The last type of manual tests that we use is accteptance tests. During this process, our QA specialists check to what extent the application coincides with user expectations. In case of any irregularities during this process, the software is corrected and not sent to production.
Additionally to manual testing, we also use automation. For this purpose, we use two automation tools Selenium and Cucumber. The first one is a web browser automation tool. It is used to automatically test the user interface. Selenium is also responsible for performing user interface tests. While Cucumber is a behavior-driven development tool that can be used with Selenium. It is typically used by non-technical teams and used to perform acceptance testing. An interesting fact is that Cucumber was originally created in Ruby. However, over the years the framework has evolved so much that it is now supported by many programming languages.
If you want to see how the testing process affects the final outcome of the project, then we encourage you to visit our Case Studies. There you will find many of our solutions supported by proper testing.