Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

TDD Coverage

Options
  • 19-01-2013 7:16pm
    #1
    Registered Users Posts: 1,466 ✭✭✭


    I started to play with TDD recently, But keep coming across something that is causing me a conflict.

    My initial understanding of TDD was to get maximum code coverage, so any small change that impacts existing code will quickly get picked up by one or more of the tests.

    This is fine in theory, but involves exposing more of a class that I would like, just to allow me to run the tests on the internals of the class.

    This is my conflict, what are others opinion on this ?

    An example would be that the code i'm creating needs a 3d array of fixed dimesions. I would like to test that I have created the array and that it's of the correct size. the array is an internal mechanism and shouldnt be exposed, but is required to do size tests on it for the unit test.


Comments

  • Registered Users Posts: 2,022 ✭✭✭Colonel Panic


    Don't unit test that sort of thing. Just test the public interfaces for your classes. Set up a class, call methods, assert that the results are as expected. Also set up classes, do things that you expect to fail and make sure they do. This should go a long way to cover your expected code paths. I have no idea what language you're using here, but mocking frameworks tend to come in handy about now.

    If you want to make sure the array is of the correct size, at the very least, use an assert and if you must throw a runtime exception or something in the constructor.

    Also, with TDD, you write the test for expected functionality, then the code so you're already doing it backwards unless you plan to use TDD from now on.


  • Registered Users Posts: 27,161 ✭✭✭✭GreeBo


    As above, you dont test private methods.
    You should however be testing all the branches of your public methods, which presumably will be calling those same private methods?

    80-85% branch coverage is a pretty high target.
    100% is not always worth it IMO.


  • Registered Users Posts: 1,466 ✭✭✭Smoggy


    Here's what I have done :

    I had a requirement that I needed a game arena of 8 x 18 x 3.
    I set up a test to create a class called playarea.
    ran three assert statement to test the array dimesions
    Red - the test failed - no shock, as it didn't compile.
    I created a new class called playarena, in the constructor I created an array of the required size.
    exposed the array (really dont like this) to test the dimensions.
    Green - the test passed. However the code is nasty.
    Refactor - this is my conflict, bad code to make a test work for me.

    Where as in reality, If I was a writing this as code first I wouldn't be exposing the array, as it's very much an internal mechanism.

    Now if I want this functionality in my code, but have to write a test first and the functionality doesn't expose a public interface, how do i implement and test this requirement ?

    It's kind of catch 22, need the code, but can't test as it has no public interface.as the test is first, but i can't test the code. It doesn't get implemented.


  • Registered Users Posts: 2,022 ✭✭✭Colonel Panic


    Just to confirm. The test you want to do is to confirm that the array is the correct size? Who specifies the size? I don't get why you can't throw an exception if the array isn't created as you expected. I mean, if something like that happened at runtime, it's a showstopper surely!

    I would be testing that my code to handle the exception gets called rather than anything else. You're going too low level!


  • Registered Users Posts: 1,466 ✭✭✭Smoggy


    I think the issue is, I can't develop it, if I can't test - as the test is first.
    I can't test it if it doesn't expose a public interface.
    So a trivial requirement specified above can't be implemented, as it can't be tested.

    I might be making a mountain out of a mole hil :S


  • Advertisement
  • Registered Users Posts: 2,022 ✭✭✭Colonel Panic


    Bigtime! You're getting hung up on the TDD dogma. Write the code, write your tests, new features? write tests then code.

    Also try and test stuff at a higher level. Don't unit test classes that represent your data models, test the classes that operate on your data!


  • Registered Users Posts: 27,161 ✭✭✭✭GreeBo


    What code will be using/manipulating the array?
    Im guessing that code will need to access the array, so either you have some accessor, or you make the assumption that the array was created correctly and you test the methods that operate against on the array and check that their results are correct.

    but +1 dont get too stuck into having to write a test that calls non existing classes/methods first.


  • Registered Users Posts: 1,466 ✭✭✭Smoggy


    I think my understanding of the TDD process was to write a piece of code, first I had to have the test.

    There will be code that is using this array, let say for the sake of it, a function called MovePiece(), but to call this code the array needs to be in place. Therefore a test in place for it.

    As stated in the above post I think i'm following my understanding of TDD too rigidly making the development process very difficult.

    Thanks again for your input.


  • Registered Users Posts: 27,161 ✭✭✭✭GreeBo


    Dont test internals, only test stuff that can be called by something else, i.e. public methods.
    If you write these tests correctly (and check coverage with something like cobertura) you will automatically cover all the internals.


  • Registered Users Posts: 2,149 ✭✭✭dazberry


    Just to confirm. The test you want to do is to confirm that the array is the correct size? Who specifies the size? I don't get why you can't throw an exception if the array isn't created as you expected. I mean, if something like that happened at runtime, it's a showstopper surely!

    I would be testing that my code to handle the exception gets called rather than anything else. You're going too low level!

    I would tend to agree with this.

    But if the array should be testable (it may not be a simple array, it could be a more complicated structure that requires some element of initialising for instance), perhaps it should not be the responsibility of the playarena class to manage the arena itself - SRP?

    In that case, you could write a class with the sole responsibility of instantiating an "arena", that would be testable in the way you imagine. You could then - using dependency injection - inject an instance of the arena into the playarena class, which would be separately testable.

    The more you push the instantiation of these dependencies outside of the classes that would have previously instantiated them and references via interfaces or abstract classes (interfaces over implementation) the more you have the ability to mock the references in a way that you can pass very specific and known dependencies and then specifically test your class - "all other things being equal".

    The thing about TDD (and unit testing) to be really effective is that it needs to be dependent on other techniques, SRP, LSP, DIP (SoLiD), Seperation of Concerns (MVC/MVP/MVVM/MVM etc....), DI, IoC ...

    D.


  • Advertisement
  • Registered Users Posts: 27,161 ✭✭✭✭GreeBo


    ^ a PlayArenaFactory would make a lot of sense, inputs are various arena dimensions, output is an object that will conform and respond to PlayArena commands.
    If it starts getting more complicated, use a builder maybe...

    Forcing you to code against a PlayArena interface would make it a more extensible app
    (what if it should suddenly be a 2D or 4D (?) arena)


  • Closed Accounts Posts: 2,256 ✭✭✭Molly


    While some say not to test internal methods, I believe it can make your life a lot easier if you do (especially if you don't use TDD). There are some frameworks that allow you to test private methods and are worth exploring (Powermock). You could write your own code using reflection to do it as well.


  • Registered Users Posts: 27,161 ✭✭✭✭GreeBo


    Molly wrote: »
    While some say not to test internal methods, I believe it can make your life a lot easier if you do (especially if you don't use TDD). There are some frameworks that allow you to test private methods and are worth exploring (Powermock). You could write your own code using reflection to do it as well.

    We had this exact argument in work last week.
    Why would you want to test private methods? You dont care how it does it, as long as it does it correctly, so test *all* the branches of your public methods and you test the private ones for free.

    Otherwise you are just duplicating test effort, or worse, skipping branches of your public methods...the ones that everyone else is relying on!


  • Registered Users Posts: 2,494 ✭✭✭kayos


    If you have a private method not getting covered by testing a public method what the hell calls the private method...... If its a case of the private method is not getting called in any of your public method tests then you need to expand those rather than directly testing the private method directly.


  • Registered Users Posts: 2,089 ✭✭✭henryporter


    Might be no harm for the OP to go back to first principals - I always thought that Robert C. Martins bowling game does a pretty good job of introducing TDD by example: http://www.slideshare.net/lalitkale/bowling-game-kata-by-robert-c-martin


  • Registered Users Posts: 1,466 ✭✭✭Smoggy


    Might be no harm for the OP to go back to first principals - I always thought that Robert C. Martins bowling game does a pretty good job of introducing TDD by example: http://www.slideshare.net/lalitkale/bowling-game-kata-by-robert-c-martin

    Thanks - I will give this a go. Good old Uncle Bob huh :)


Advertisement