Just out of interest really. About the middle of last year at work we decided to start strick full coverage unit testting on all code. A learning process that changes how you code even about how you think about code.
8+ months later and I am now over the initial fights against it and would never consider cutting code without related unit test code in place. It has saved us so much time, heartache and pain in tracking down bugs that would otherwise only surface and slap you in the face after the code was in the hands of a customer.
Just wondered what other people have played with unit test system like nUnit and what they though of the techniques and did it also effect how you thought about code.
I usually write a specific set of regression tests for each project, as I tend to write little hacky, non-gui apps, which have a very specific purpose it kinda makes a lot of the unit testing apps out there a little redudant.
Used Boost.Test when working on a Unicode library i did for my Bachelor's degree. When working against a spec like that unit testing is invaluable. When implementing some of the algorithms outlined in the spec we basically wrote the tests first and then started writing the algorithms. Being able to quickly throw something together and then just test to see if we got it right saved us so much time and effort. It's quite a motivational factor too as you have a clear cut goal to work against, and you always see yourself progressing as more and more test cases come out valid. The tests also helped us a lot in identifying a few strange bugs only apparent on one platform.
These days I don't unit test as much as I used to. I keep telling myself it's a waste of time, even though I know it really isn't. It's too easy to get lazy about stuff like that.
I think that's the key. It can be incredibly useful for specific kinds of programs, but throwing unit testing at everything you make is a little heavy handed. I reckon if I was ever going to make something like a videogame, then unit testing would be insanely valuable, but for most of the smallish Windows apps I make it's really not that helpful, except in specific instances. I think it's another case of a tool that's valuable when used in the correct way.
Yep. I find I'm having a hard time doing it when the project is a bit more fluid. When the overall design isn't obvious from the start and when the requirements change during development (which is most of the time ). In these cases you end up having to change both the code and the tests every time you make a change and that feels wasteful.
Never used any unit testing but I've been telling myself I'll learn to use JUnit for a long time. I know a couple of people at work who swear by it and I'm pretty sure I'd find it invaluable but I just haven't got round to it.
To be a little bit more explicit than Wikipedia; if you have a function doing addition for instance, you write a unit test to make sure the function does indeed return 5 if you pass 2 and 3 to it.
Currently I am working on the web services and business logic side of things hence the strict coverage. I have created a framework that automatically tests all properties and validates use of attributes correctly and reports on test coverage etc.
I know what you mean on GUI. I get the feeling something like the Data/View/Presenter pattern will allow simple unit testing all the way up to just below the GUI. This pattern moves all logic out of the form so that only code that populates and manages control interaction remains in the form, the stuff that is hard to test.
Also changing your techniques to use dependency injection allows use of mocks and the like which makes object build up and tear down easier in your test
Actually I find its the vital time to work with tests. The other side of the "extreme programming" (I hate that term lol) is that you refactor, refactor, refactor and the tests around your objects are what gives you the ability to do this and know you have not broken anything subtle when you do.
I have to say, 8+ months in and up to about 80% coverage (We started with some older code we are retro fitting tests for) and the benefits show. Less bugs, easier to refactor etc.
I did fight it for a while but now the project has reached the 200+ objects size it has made life and code management ar easier
Unit testing is definately good for complex stuff. Personally I only used it once when I wrote a bigger program for university with 3 other guys and we tested each others code. For "personal programming" it's imo too much extra work and writing tests for your own code is kinda... Well you knwo your code
But don't you find yourself running around adapting your tests if you need to refactor some class hierarchies or something high level like that. It's easy enough when the overall design is more or less locked down and you have to refactor the implementations of functions and classes, but I sometimes find myself changing both design and implementation around and that's when I feel the tests are in my way more that helping me.
With unit testing you are making sure the function does what it is meant to do. If you refactor those tests might still be valid in which case you relocate them because they still represent functionality you need. If not you dump them because they no longer serve a purpose.
You do not need to re-test the units lower in the call stack, just that they are called when expected from within your function. The unit tests for the lower level code that built the results object mean that has already been tested.
If you had a function that say did this
public class MyMaths { public MyClass PerformCalculation(bool selector, int amount) { if (selector) { return BasicMaths(); } else { return ComplexMaths(); } } }
you only need a test like this
[Test] public void TestPerformCalculation() { MyMaths obj = new MyMaths() Assert.AreEqual(11, obj.PerformCalculation(false, 10).SomeProperty, "Basic maths should result in 11!"); Assert.AreEqual(12, obj.PerformCalculation(true, 10).SomeProperty, "Complex maths should result in 12!"); }
This is because you already have tests for the call to BasicMaths() and ComplexMaths() that make sure the methods perform as you expect so all the test for PerformCalculation() needs to do is validate that the correct method is called when you expect.
If the method you are testing requires construction of complex object structures you can use interfaces to replace the need to build up large object structures with mocks that return known values just so you can test the paths through your code.
What unit tests also do is change the way you structure code. You start cutting up the code and restructure it so that testing becomes easier, so that each method is more focused and single minded. It stops you writing those long complex functions that have 100's of paths through them because testing them requires 100s of tests. You start think in far more generic patterns.
The only real complexity then is in the real guts logic and when you look at that you soon realise most of that can be pulled apart into building blocks. The sort of stuff I am working on is complex multi currency accounting at present as even this chunks into small blocks.
Unit testing is white box testing, not black box. A mistake I made early on and which did result in too much work.
I guess that's where the sticking point is for me. Having another dependency to modify when I change something around. Even if I just end up throwing the test away I've in a way wasted the time I spent writing it.
I know it's just me being lazy, but maintaining tests does feel like a bit of a chore for the majority of the projects I work on (mostly simple web work these days). I'm considering if for one of my larger hobby projects though (game engine), but I'm still not sure it's worth it there as the entire thing gets rewired every couple of months.
I'm probably at the extreme end of this discussion. In my real life job, I worked on a project that generated JUnit tests from submitted code. See <http://www.junitfactory.com>.
This is usually nice to have for legacy code that has little to no tests written for it. The tests are easy and cheap to regenerate, so the coding model looks something like: Generate tests -> Run tests -> Verify and fix failures -> Add features -> <repeat>
The initial version of JInSim I wrote test first. It's a good way to make sure you've thought through the different user scenarios within the program you're writing, and end up with tests at the end. If you have tests you can be more confident that changes you've made in your code don't break something else. With modern IDE's refactoring capabilities, even the test maintenance isn't as much of a hassle as you'd think.
The biggest mistake I made when I submitted JInSim to SourceForge was not checking in the tests along with it. Tests have another nice side effect in that they serve as a type of documentation for the code. In an open source environment, this is invaluable when adding developers. If they add code and break the tests, they have something to point to when asking questions from the seasoned developers on the project.
Having said all of that, it's very hard to convince someone who doesn't believe in the value of unit testing to write unit tests.
I guess thats it. I went through months where I felt it slowed me down etc. It's only when you have them in place and you start on a big ish refactor or add a new feature that you understand it can make coding faster because you don't spend 3 weeks later down the line looking for that nasty bug
Having the ability to dive in and change knowing you have not buggered anything existing in a subtle way. The sort of thing where you change a common library object that is used in loads of places throughout your code. Where the change breaks that one path you didnt bother to test as it was thought to be unrelated