Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm going to start my first real project in Ruby on Rails, and I'm forcing myself to write TDD tests. I don't see real advantages in writing tests, but since it seems very important, I'll try.

Is it necessary to test every part of my application, including static pages?

share|improve this question
9  
This really isn't a ruby on rails question. it's more of a TDD question. –  Jon Strayer Mar 9 '12 at 17:42
4  
@JonStrayer: Is it? Are you certain the answer would be the same for RoR as .NET? I would suggest that by design RoR has deliberately reduced the cost of testing, while not having type-safety in the form of a compiler massively increases the benefit of testing. –  pdr Mar 9 '12 at 17:49
    
I don't know that this is exactly a duplicate question, but there are some great answers in What are the disadvantages of test-first programming? and When is it appropriate to not unit test?. –  jcmeloni Mar 9 '12 at 18:13
1  
For some reason, this question makes me want to post an image macro of Captain Nero yelling "TEST EVERYTHING!!!" –  Mason Wheeler Mar 9 '12 at 23:17
3  
Not seeing the real advantage in writing tests and writing them out of blind faith doesn't really sound right. Go on without writing tests, after a while you'll experience an unexpected regression and know why you're testing. –  ZJR Mar 10 '12 at 3:07
show 4 more comments

11 Answers

up vote 45 down vote accepted

TDD isn't about testing, it's about design. Writing the tests forces you to think about how the class is supposed to work and what kind of interface you need. The tests are a happy side effect that makes it easier to refactor later.

So, with that in mind, what is the behavior of a static page and what is the interface?

My first response would be "none" and "none".

share|improve this answer
    
so no tests for static pages? –  Matteo Pagliazzi Mar 9 '12 at 17:44
    
TDD is, to a degree, about design. But you still need an architecture. Without an architecture in mind, it's difficult to imagine how one would grow organically out of a bunch of tests. –  Robert Harvey Mar 9 '12 at 19:06
    
@MatteoPagliazzi Depending on the level of the testing (unit tests / integration tests / etc), perhaps one or two, to confirm the static pages are accessible. But that's too high-level for unit tests. –  Izkata Mar 9 '12 at 21:43
1  
@RobertHarvey I didn't say don't test anything. I said don't unit test static pages. –  Jon Strayer Mar 12 '12 at 13:14
    
@JonStrayer: TDD'ers tend to hold up TDD as some magical elixir for design; I apologize if that's not what you meant. :) –  Robert Harvey Mar 12 '12 at 14:42
add comment

If you're truly using the TDD methodology then you don't write code without first having a unit test you are trying to make pass.

share|improve this answer
2  
yes... but for example in a static page what should I test? the existence of it? that the content and links exist? maybe i'm wrong but it seems a waste of time... –  Matteo Pagliazzi Mar 9 '12 at 17:06
1  
I tend to think that the TDD methodology is applied to your logic. Is your static page an html file? An MVC view that never changes? If the latter case I guess you could test that your controller returns the proper view. I think the more important thing is to remember that TDD should be helping you develop against your specification not just "test"... –  wessiyad Mar 10 '12 at 17:58
    
I assume you simply serve a static page with a component of the framework. If none of your methods are touching that page, there is in fact nothing to test. You don't also need to test Rails. I think somebody has that covered. –  Erik Reppen Mar 22 '12 at 22:00
add comment

It's always a cost-benefit analysis. What's the cost of the feature breaking to you? If the cost is high, then test well and thoroughly. If the cost is low, test lightly or not at all.

There's also the cost of time-to-market to consider. Maybe it's better for you to deliver a mostly working feature than to be late delivering a completely working feature.

It's almost impossible to answer these questions in the general IMO.

I think it's more important to preserve the ability to test in the case that some feature turns out to be more important than you originally realized.

share|improve this answer
    
Also, I would assume bugs in a static page would be MUCH easier to fix than logic errors, design errors, and the type of things TDD is normally used to prevent. Both discovering and fixing errors of static pages are likely to be fairly easy, and its my impression that TDD is used to shorten both of those processes when they take longer than is desired. :D –  Gordon Gustafson Mar 10 '12 at 0:36
    
I wouldn't assume that. If you have ever dealt with obscure browser version behaviors or strange javascript memory issues you've likely gotten quite a workout. More sometimes as back end languages can be a little more reliable and standard. sometimes. Maybe you're talking about static as in html and no javascript though. –  Michael Durrant Mar 10 '12 at 2:58
add comment

I would say "yes". If you have tests covering even the simplest features and code, then you can have confidence that adding new code doesn't cause in-place code to quit working. Similarly, putting in a test for every bug you encounter keeps regressions from creeping back in.

share|improve this answer
    
"then you can have confidence that adding new code doesn't cause in-place code to quit working" in that way i shouldn't touch any piece of code i've written before and jus adding new methods? –  Matteo Pagliazzi Mar 9 '12 at 17:08
    
Well, no. But unforeseen and unplanned dependencies between code that currently "works" can lead to problems if you add new code that changes those dependencies. Also, if you get the test wrong, which I think is pretty common, you have to modify the test itself, and then, perhaps, modify the code arising from that test. –  Bruce Ediger Mar 9 '12 at 17:49
    
@Andy That's absolute nonsense. Testing property setters and getters is both trivial and VITAL. If they don't work, generally the whole class falls apart. For example, in a multithreaded application, if the set doesn't prevent concurrent gets, then you'll get a corrupted data issue that can take hours to get to the bottom of, because the data source will be correct, but the get result will not Or if your set fails to also update the update time, then your data can become impossible to sync You get the idea. If setters and getters were genuinely trivial, you could just make the property public –  deworde Mar 9 '12 at 20:51
    
@deworde I'm afraid making instance members thread safe isn't all that common. Its more usual to control access to the non-thead safe type than to try to make them thread safe. Anyway, what to test is a cost-benefit thing, as another answer states. you can spend time writing tests for getters or setters or you can test the actual behavior your system is supposed to encapsulate. –  Andy Mar 10 '12 at 0:28
add comment

Yes, you should test everything...

You won't necessary be able to write automated tests for everything. For your static pages, look into using Selenium http://seleniumhq.org/ for making sure things are correct.

From my experience, some front end things are next to impossible to write test cases for but that is why you would actually want to test using the Mark 1 eyeball.

share|improve this answer
    
I disagree. If you can't make it happen either via a mock or passing in data, then why have it in your code. Getters and setters don't need their own tests put would be tested via other unit tests of the system for verifying the expected functionality. –  Schleis Mar 9 '12 at 19:31
    
Sure, setters / getters are tested indirectly with other tests but when someone says "test everything" I assume they mean create tests specfically for those kinds of things. I always tell people "test the important things." Things like setters and getters don't fit into that definition for me. –  Andy Mar 10 '12 at 0:31
add comment

Testing is as important as coding. You must heard the saying "If something can go wrong, it will". INMO, Out of the many techniques of software engineering that are employed to enhance quality, Testing is the most valuable one in helping you find problems early.

While testing everything is not possible (specially with small teams and large systems), it does not mean you skip testing altogether. Is testing worth it? See the section "Finding faults early" in See Wiki-SoftwareTesting.

share|improve this answer
add comment

As others have mentioned, in Ruby on Rails testing it is far more important than in (most) other languages. This is due to the lack of a compiler.

Languages such as Delphi, C++, VB.NET, etc... are compiled languages, and your compiler will pick up a lot of mistkes such as typos in calls to a method. In Ruby on Rails you will only know if there is a typo or a mistake in your code if that particular line of code is run or you are using an IDE that shows visual warnings.

As EVERY single line of code is important (otherwise it wouldn't be there) you should test every method you write. This is a lot simpler than it sounds if you follow some basic TBDD tools.

I found that Ryan Bates' Rails Cast on How I test was invaluable to me and really highlighted the simplicity of TBDD if done correctly.

share|improve this answer
add comment

To answer the question, think about "what could go wrong here". In particular, if you change the "code" (markup/whatever), how will you have confidence that you haven't broken the page. Well, for a static page:

  • it might not render
  • it might render incorrectly
  • the JS might not load
  • the paths for images might not work
  • the links might be broken

Personally, I would recommend:

  • write a selenium [1] test that checks for one string you expect on the page (near the bottom if possible). This validates that it renders.
  • check there are no JS errors (I think selenium allows this)
  • run the static pages through a html validator, and if possible, a link checker.
  • I haven't found a tool I like to validate JS, but you might find success with jslint or jshint.

The take away here is that you want something that is repeatable, easy to use, and will run automatically in your test runner.

share|improve this answer
add comment

TDD Tests can also be living specifications if written that way. The names of the test methods should make sense to a business user.

share|improve this answer
add comment

I would say to not start with TDD. Make an informed decision when you've spent more time learning architecture strategies in general. TDD won't let you skip that homework although you might start believing it does.

Here's my problem with it. When you say it seems like a lot of wasted time on stuff that will never break TDDers say you'll appreciate it when that one thing you didn't anticipate in a huge chain of dependencies gets busted. When you point out that it's impossible to predict such things before you write your app, which is uh... why we test, they tell you it's really more about design and not testing even though the testing comes in handy.

But aren't giant chains of unpredictable linked dependencies the product of crappy design?

So which is it?

Here's a thought. Let's not have huge complex chains of dependencies in the first place by considering the following two principles of object-oriented design from Design Patterns:

"Program to an interface, not an implementation"

That is to say, your objects should not care who is doing the calling or how they were made. Only that the proper args were fed in and that the methods they call from other objects they're directed to work as expected. Your chain of dependency in most cases should be at one linking point, the method call on the part of the caller and the spot where the args get dropped into your methods. That's where you log and validate and send useful messages for debug when things crap out.

And:

"Favor object composition over class inheritance"

Who's the dummy? The guy who did something to a class in a convoluted cascading inheritance scheme involving like 30 classes resulting in fringe case breakage, or the dev who came up with that architecture in the first place? TDD might help you get to the bottom of issues inside that leaning tower of class Pisa sooner than you could have without but does that make it any less painful to attempt to modify one of the endpoints of that code disaster the next time?

And that's where I get to the thing that bugs me. Does TDD really help design or does it enable bad architecture? It seems to me like it has potential to be a self-fulfilling strategy. The more your team doesn't have to own responsibility for poor architecture, the more helpful those granular testing components seem to become, but ultimately your app becomes an increasingly bigger PITA to work with (assuming they never gave much thought to architecture in the first place). And failure to acknowledge the consequences of that is hands down, always the most expensive mistake you can make when working on an application that's meant to be upgraded and modified over time.

share|improve this answer
add comment

Just to add to all the already excellent answers, here's my thinking on what to test, and what not to test:

Do test:

  • business logic
  • application logic
  • functionality
  • behaviour,
  • so, everything, really, except:

Do not test:

  • constants
  • presentation

So there's no point in having a test that says:

assert wibble = 3

and some code that says

wibble = 3

And there's also no point in testing presentational things, like whether the icon is in perywinkle blue, what font you've used for headings, and so on...

So, you ask, "should I test static pages", and the answer is: you test them insofar as they are part of your site's functionality, business logic, or behaviour.

So, in our app, we have a test that checks that the terms & conditions are available from every part of the site - for anonymous users, for logged-in users, from the dashboard, inside app screens etc. It just checks that there's a link called "terms and conditions" on each page, that the link works, and then the test says that when it arrives on the page, it "looks like" the Ts & Cs - just enough to reassure yourself it's the right page, without "testing a constant", or "testing presentation"... so you could check that the text is correct, for example, without checking the particular font size or text layout...

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.