30

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?

10
  • 9
    This really isn't a ruby on rails question. it's more of a TDD question. Commented Mar 9, 2012 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
    Commented Mar 9, 2012 at 17:49
  • 1
    For some reason, this question makes me want to post an image macro of Captain Nero yelling "TEST EVERYTHING!!!" Commented Mar 9, 2012 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
    Commented Mar 10, 2012 at 3:07
  • 1
    Wait until you decide to re-structure your code. Any time massive changes are introduced, you need to verify functionality. Without tests you'll need to go through your application and test all of the functionality manually. Introduce another large update and you'll have to do it again. Unit tests are just a 'cheap' way to make sure everything is working as expected. Commented Apr 28, 2012 at 19:56

11 Answers 11

49

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".

5
  • so no tests for static pages? Commented Mar 9, 2012 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. Commented Mar 9, 2012 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
    Commented Mar 9, 2012 at 21:43
  • 1
    @RobertHarvey I didn't say don't test anything. I said don't unit test static pages. Commented Mar 12, 2012 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. :) Commented Mar 12, 2012 at 14:42
34

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.

2
  • 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 Commented Mar 10, 2012 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. Commented Mar 10, 2012 at 2:58
8

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.

4
  • "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? Commented Mar 9, 2012 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. Commented Mar 9, 2012 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
    Commented Mar 9, 2012 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
    Commented Mar 10, 2012 at 0:28
3

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.

2
  • 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
    Commented Mar 9, 2012 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
    Commented Mar 10, 2012 at 0:31
2

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.

2

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

2

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.

1

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.

3
  • 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... Commented Mar 9, 2012 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
    Commented Mar 10, 2012 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. Commented Mar 22, 2012 at 22:00
0

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.

-1

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.

-1

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...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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