Testing and Rspec are new to me. Currently I'm using Rspec with Shoulda and Capybara to test my application. It's all fine to test models, controllers, helpers, routing and requests. But what should I exactly test in views? Actually I want to test everything in views, including DOM, but I also don't want to overdone things.
These three things would be a good starting point
Use Capybara to go start at the root of your site, and have it click on links and whatever until it gets to the view you want tested.
Make sure what ever content is supposed to be on the page, is actually showing up on the page. So, if they 'user' went to the Product 1 page, make sure all the Product 1 content is actually there.
If different users see different content, make sure that's working. So, if Admin users see Admin-type buttons, make sure the buttons are they when the user is an Admin, and that aren't when the user isn't.
Those 3 things are a pretty good base. Even the first one is a big win. That will catch any kind of weird view syntax errors you may have accidentally introduced, as the syntax error will fail the test.
At my work we are using RSpec only to do unit testing.
For business testing or behavior testing we are using Cucumber that is much more readable for the business and IT guys.
It's like a contract that you sign with your business or it's like a documentation that you can execute.
Have a look at Cucumber: http://cukes.info/
I use view specs to verify that the view uses the IDs and classes I depend on in my jQuery code.
And to test different versions of the same page. E.g.:
I would not want to create two full request or feature specs to check that a new user sees welcome message A and a returning user welcome message B. Instead I would pick one of the cases, write a request or feature spec for it, and then a additional view spec that tests both cases.
Rails Test Prescriptions might be interesting for you, since it has a chapter dedicated to view testing.
Related
I am going to work on a new project where we have 5000 test cases/scenarios. Each scenario has coming functions like login, Amount Transfer, etc. Therefore each scenario will have certain data. So, in case 5000 scenarios, I feel it will very difficult to handle the data. Because even if the password of the Login user gets changed, then I need to update the Password 5000 times in all the scenarios from different feature files. This goes against the idea of Automation where we are targeting to reduce the manual effort. So I am asking here if anyone has any idea/workarounds to handle such situations I hope there should be. Thanks.
Typically speaking you would create a new user for each test and discard it at the end of the test.
You should also not describe all the details of the users that are created. These often are not relevant to the test and merely incidental details. Rather you would use a template and only describe the changes made to this template in the feature file. If for auditing reasons you have to describe this template, you can write a scenario that tests your template.
I wonder if something is wrong with our approach to the POM. In many examples on the internet I find this pattern used in a way so that your test script looks like this:
pageObject.doSomethingWithElement(parameters...)
For us it was more natural to do it like this:
pageObject.element.doSomething(parameters...)
So we don't need to implement what can be done with an element in the page class but just simply define those actions in the test script. For some reason that felt more natural for us similar to the fact that there is
System.out.println()
System.err.println()
instead of
System.printlnOut()
System.printlnErr()
Do we miss some disadvantage of our approach?
There's no advantage or disadvantage when choosing between those 2 models. But I think you are slightly misunderstanding the recommended approach. The idea is not to pageObject.doSomethingWithElement, but to do something with a functionality of the page, pageObject.doSomething if you want.
If you look at Selenium examples for instance, one of the first examples is public HomePage loginAs(String username, String password). Nothing in this function is about elements, it's about functionality of the page, easily expressed verbally, without any reference to elements involved. I can read this function as: when user is on Login page, and user provides username and password, on successful login, user is redirected to Home Page. Which sort of provides a natural BDD interpretation of page model.
The advantage of such approach is that your tests are much more readable. Instead of something like:
loginPage.username.setValue(...)
loginPage.password.setValue(...)
loginPage.loginButton.submit()
// how do I get a homepage from here?
this model allows to have
HomePage homePage = loginPage.loginAs(...)
Done!
Also from maintenance perspective: if developers change elements on Login page, it might be important for 20 tests that deal with login functionality. But you want other 980 tests you have to be completely unaffected by their change, since they only use login on their way to test other parts of functionality. So they can remain completely oblivious to changes in login elements, as long as login itself keeps working as it should.
So I think the choice is not between various ways your page could express element-related functions, but with whether your page should express elements at all, or concentrate on functionality it provides, regardless of the elements.
I recommend reading that page I quote here, it gives a very good idea of what page model is all about.
Suppose I have a web page with several links on it. Also it has few buttons which execute some JavaScript.
So should I create one Java class for testing each of these links and elements or should I test all the links in just one test method and other elements in another one(so ending up with two Scripts).
Is there a another way of gouping these tests.
Thank you.
I have found that writing test cases based on actions is much more useful than writing based on pages.
Obviously, we would love to have everything automated. But realistically, this isn't possible. So we test what is most important...which happens to be: 1. The primary purposes of the product you are testing, and 2. The security of the product.
To make this easier to understand, lets say I have a Checkout page.
If I were to test based on a page, I would make sure every link on the page would work. I would verify that I can type in a new number in the quantity field, and make sure that the page verifies that the credit card number I type in is correct.
This method would somewhat test Security, but beyond that, it would test the UI. What would happen if I clicked on the Checkout button, and I was sent to the right page, but the item I was trying to checkout disappeared? That is a huge problem, but the test based on the page would work.
However, if I were to test based on actions (go to this page, add to cart, type in personal information, and then checkout), now I have made sure that the most important part of your program works, checked security, and even a little UI testing.
All in all, write your testing to do what the average user would do. No normal person is going to sit on the same page, testing out every little feature on that page.
It depends on whether you like to see 1/1 tests passed or 2/2 tests passed.
I've been looking for ways to test a Rails 3 app that has quite a lot of JS code for its rich interface. I tried with Capybara, but that didn't work out, so now I'm giving Jasmine a try. But I'm having a hard time understanding how I should go about it.
From what I gathered, Jasmine alone is good for testing the JS components of a site, but what if I want to test the interface directly? I need something like:
describe "Sign in"
Visit '/home'
When user clicks "Sign in" link
The sign in form should appear
Can I actually do something like that with Jasmine? So far, my tests are included on a results page generated by the rails-jasmine gem and obviously they run over that DOM, not over my site's DOM.
I'm now trying to use evergreen, but I get the same result (I can't even include jQuery).
Any ideas?
Thanks!
To answer your question - no, Jasmine will not inherently function in a way which will let you navigate your site and test at such a high level, like an integration test with Cucumber.
Jasmine is built primarily to test the API of your js, and so essentially you will only be able to test URL routes or something with it if they are part of your API.
For example, you can test how a Backbone Router will respond to your window's current location, or navigating from one location to the next, but that is because Backbone Routers explicitly handle URL locations.
This might help: http://railscasts.com/episodes/275-how-i-test
You could try using jasminerice with fixtures. If the intent is to test the JS DOM interaction, then fixtures would be the way to go.
But if the idea is to test the server interactions as well, then going with something like cucumber makes sense.
I'm a big fan of keeping application logic in the servlet, and keeping the JSP as simple as possible. One of the reasons for this is that any good web designer should be able to expand upon his HTML knowledge to build in a few JSTL tags to do simple iteration, access beans, etc. We also keep the more complex/ajax/js components behind a tag library (similar to displayTag but for our own components).
Most of the time everything works out ok - The servlet does any SQL it needs to, and stores the results in beans for the JSP to access. Where we have a problem is when the records we wish to access are specified by the design.
The clearest example would be the home page - it needs to be eye-catching and effective. It doesn't need to be uniform like rest of the site. There are lots of one-offs or "special cases" here, where we want to query a particular product record, or whatever.
What the designer really wants is a way to get a product bean by the product id so he can access the properties as normal. We obviously don't want to query for all products, and I don't want to query in the presentation.
I'm pretty sure I'm asking the impossible here and that I have to give something up. My question is what?
EDIT
Am I wrong in thinking that all application logic should be complete before calling the JSP? I was under the impression it was considered best practice to do all querying/calculating/processing in the servlet then pass (fairly) dumb beans to a (very) dumb JSP.
There are a couple of methods whereby the actual complexity of the query can be encapsulated in another class (custom tag or bean), and the JSP can call it. This
keeps the JSP simple (goal 1) but the JSP is still "triggering" the query - quite
late in the process.
Have I got this totally wrong and it's fine to do this.
Is it a general rule, but perfectly ok to do this in this instance.
Might I run into problems?
EDIT - Example
I'm hoping this example will help:
The home page isn't a "template" like the category/search pages - it is custom designed to work very well with say a marketing image and a couple of specific product images. It does however have information about those two products which should be obtained dynamically (so the name, and importantly price) stay in sync with the db.
The servlet can't know which products these will be, because if the designer wants to change them/remove them/add more, he should only have to edit the JSP (and possibly XML as one answer suggested).
If I understand correctly, you have logic in the JSP that wants a particular product, but at this point you don't want to query from the DB, and its too late for the servlet to be aware of it.
(A side note, while I respect your will to maintain separation of concerns, the fact that this is an issue clearly shows that your framework has too much logic in the presentation tier...but since we probably can't fix that...moving on).
My recommendation is that your designer creates a configuration XML file that contains whatever special cases it needs for the frontend, and yours servlet can read that, then pass dumb beans back to the JSP.
OR...you break things down into multiple requests using XMLHTTPRequest and call back to the servlet for each individual query, then assemble the page on the client.
It sounds like you need better separation between the display and database code. You should have separate classes that just deal with interacting with the database, and know nothing about display.
Then you just create a method that will look up the product by id and return that bean so the display can pull out the attributes it wants.
You need to create a custom bean which will perform your queries for the front end. Actually, it's probably more like a few beans to get the data for you, according to what you say here.
There's no problem with doing that from a design perspective; it's just that the specific design of the home page has more heterogenous requirements than the rest of your site. Make sure your designer knows that he needs to communicate his needs well to the development team to create the BO for your homepage (or whatever) and thing should go fine.
You are not wrong in thinking that all application logic should be complete before rendering the JSP.
If there is a need to fetch more stuff for displaying in your JSP, it would be another request to the server and another Page cycle. If you are looking for 'interactive' loading experience, you could use AJAX.
In a single page life-cycle, I find it hard to understand why do you have to invoke database calls from a JSP. Hasn't the page been previously posted with all the required form variables to help you find the data in Servlet/Helper classes?
If you could give an example of a case, it would be helpful.
[Edit] Looking at your example, yes your designer (or the admin of the site) should set that information as a configuration, not a part of JSP. Or, you could have a small app/admin page to maintain the information in a database so that it could be changed on the go. When you show your homepage, read the configs and load the appropriate data.
I am not sure what is the question. I f you want to have sql statements out of your jsp pages then you can put them in a property file and just read the property file from the jsp page.