13

On a current project, the powers that be want to have unit testing incorporated into our development cycle to avoid the constant amount of bugs that seem to seep into our code. The problem is that the spaghetti code is 95% percent procedural, which I've never done unit testing with (all my experience with unit testing has been with OOP code)

So my question in a nutshell is would it be wise to proceed with unit testing with our current codebase, or suggest that it be postponed until the application has been migrated to a proper OOP framework?

PS: While I tried to style this question as language agnostic, I feel that stating the application in question uses PHP and javascript will help provide more specific answers that could answer this question since from experience this occurrence occurs most with such applications.

5

5 Answers 5

14

Unit testing works well with objects, especially since it provides lots of fancy features, like mock objects, which helps creating better tests faster.

This being said, nothing forbids doing unit testing on a procedural codebase. In OOP, most unit tests are testing methods by passing some parameters to them and expecting either a result, or an exception of a specific type. This can be done as far with procedural code too; just that instead of testing methods, you'll test functions.

Note that you'll have to:

  • Isolate the functions you have to test and the ones you don't need to. In OOP, this is easy: private methods don't have to be tested because the callers will never be able to access them directly. Chances are, in your procedural code, some functions are like this and don't need tests.

  • Think about global scope. The problem exists in OOP too, but if you say that you have to test spaghetti code, chances are that the people who wrote this code have bad habits, such as using global scope too much, and doing some crazy things like changing $_GET or $_POST arrays inside functions.

  • Deal with code outside functions. This is a more complicated case, but still possible. Either you require_once a page to see what happens and catch the output through ob_start/ob_get_clean, or you do an HTTP request from the test suite and analyze the response by parsing the HTML. This is not really an UI testing: here, you don't care if a button on a page appears at the left or at the right or if a link is in big red capital letters or in small blue ones. What you care about is to find some HTML elements through DOM and compare their content to the expected one.

  • Test the response codes. require_once with output buffering is good, but you also have to test how the web application deal with errors. For example if the expected result of a test is 404 Not Found, you must do an HTTP request in order to know what the response is.

5

suggest that it be postponed until the application has been migrated to a proper OOP framework

Get some automatic tests in place before migrating to another platform, not afterwards. Add further tests while doing the migration, not afterwards. If those tests are "integration tests" or unit tests you have to decide yourself, but typically you can use your favorite xUnit test framework for both kinds.

5

The most effective way to start unit testing is to identify the class of errors that occur most often, or are the highest cost. Then create tests that target those errors.

How those test get implemented will differ between paradigms and languages. The biggest things that will impact your ability to do unit testing is the quality of the code; less so the paradigm used. Remember unit testing is about testing a "unit" of code in isolation. Anything that impacts your ability to isolate "units" of code will make testing harder.

  • use of globals
  • side effects
  • tightly coupled code
  • badly coupled code
  • a large number of conditionals
  • badly designed "units"

All these will have a higher impact on difficulty of testing than language paradigm.

4

Anytime you have a situation where you can test parts of your code automatically, unit testing can be effective. So, the question isn't can procedural code be effectively unit tested, the question is can THIS code be unit tested. That will depend upon how much state it reads and much state it sets. Ideally the answer to both is zero, but if it's not, you can still test it.

As always you need to weigh the confidence that the code is correct against the cost of gaining that confidence. Keep in mind that part of the gain for unit testing is explicitly identifying the dependencies, and in that sense it is even more effective to unit test procedural code as compared to OOP code.

-3

I don't think it's possible to do true unit tests against procedural code. The main problem being that each procedure will likely have many dependencies that cannot be stubbed out. At best the tests will be integration tests. I've done a similar thing many moons ago with VB6 modules and VBA modules in MS Access.

That said, if you can put test scaffolding around the methods causing the most pain, that has to be of value, right?

4
  • 5
    -1: Bad design and implementation is the problem, not procedural code. Just as you can write terrible OP, you can write great procedural code.
    – mattnz
    May 22, 2012 at 4:33
  • @mattnz - I'm not sure how your comment relates to what I said about being, or not being able, to unit test procedural code.
    – Rob Gray
    May 22, 2012 at 5:23
  • 7
    Procedural code does not equal spaghetti. It is very much possible to write well designed, modular, cleanly separated, high cohesion / low coupling code in a procedureal manner. May 22, 2012 at 6:30
  • 2
    A good design introduces unit-testabilty in any code, procedural or not.
    – Doc Brown
    May 22, 2012 at 6:30

Your Answer

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

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