I am a sole developer working with an offshore employer. I do realize the importance of unit testing (although haven’t practiced before) but currently, the code hasn’t ever been tested. The problem with the code is that it isn’t what I call “been moduled well”, some parts are really messy, extensive use of globals and the code doesn’t really show loose coupling. If I am not wrong, the code might require heavy refactoring before being able to be unit tested. Also, it seems the employer, isn’t quite interested in testing. He rather suggests to spend this time in building features.
So what I suggested to him is UI testing. Because UI testing is something we do every time, testing features, clicking, checking if something is not broke, it made sense to both of us to use it to automate the process of checking features and save us time.
Since I have never done UI testing before, I don’t know what possible disadvantages might be associated with using just UI testing alone or will it be much beneficial at all?
5
At my work, we started using UI tests in addition to our unit and integration tests. Of the three types, the UI tests take the longest to write and to run and catch the fewest amount of bugs. They are also extremely brittle, failing sporadically for no good reason.
Because they take so long to run and do not pass consistently, we found that it was not worth the effort to maintain them. Of course, this could be due to writing the UI tests poorly, or using a bad framework (we used visual studio Coded UI tests).
We have had much better success with unit and integration tests. In your situation, given that the code is not very modular, unit testing will be difficult as you mentioned. I think you would have much better success with integration and acceptance-level tests (test entire features at a level just below the UI).
2
The biggest problem IMHO of UI Testing exclusively is that the permutations of things to be tested, even in a relatively simple app, are too great and the level too high to catch many potential defects. Code coverage is not going to be very high.
You will probably find and locate some major items that will inhibit the users in a few scenarios (best case, worst case run through), validation issues and what not. However, you won’t find the things that say a Breaker would use to disadvantage your application and get into your data, for example.
Unit test, TDD, Functional Testing and other testing methodologies are designed around testing the code internally and at a more granular level. This makes the testing more complete and likely to catch the more insidious bugs that simple UI testing alone will miss. A combination of the above is your best bet. Sadly it doesn’t sound like you will have to much choice unless you just do it. It sounds like there are severe time constraints as it is, but note that with only UI testing your time may run over regardless.
6
I would recommend picking up Michael Feathers’ Working Effectively with Legacy Code. In the book he defines “legacy code,” somewhat interestingly to me, as “code without tests”. The impression that I get is that your situation is pretty common: not only is your code not covered by tests, but in its current state it can’t be covered by tests. The book describes some ways to deal with this situation. I won’t list them here because they a) are complicated and b) aren’t committed to my memory.
What I do if I were you is put some of the code in a “test harness”. At first I wouldn’t even worry about adding meaningful tests at all. Just get to the point where you have one or two unit tests testing trivial parts of the system. Once you have that little beachhead, from there it’s mostly a matter of expanding on the work you’ve already done (not to say that that is easy). It may feel pointless in the beginning, but a few semi-meaningless tests are better than no tests at all, and maybe after some gradual refactoring you’ll have some meaningful tests.
UI tests are not what you’re looking for. To get messy legacy code under test, you start writing Acceptance Tests. These are blackbox tests on the outer layer, but widely independent from the user interface. You can look at tools like Cucumber to get an idea about the approach.
As you’re going to refactor and improve the code, you should add unit and integration tests for new code as you go along.