Search code examples
javaagilelegacy-codeacceptance-testing

Acceptance testing a legacy code


I'm following a course in agile practices and I have a homework. During the course, I've been taught on how to use FIT for automated acceptance tests. From what I can see, FIT seems to be dying and I'm no longer sure that it is the technology I want to use for my homework. Anyway...

I have legacy system to test and everything is badly designed/coded. Of course there are no tests, and I'm not allowed to refactor or change functionality before writing any acceptance test.

For the sake of simplicity, let's say the system is a shop receipt system that prints the products list (with prices) and the total cost to the standard output stream. Something like this:

public class ReceiptSystem
{
    List<Product> boughtProducts = new ArrayList<Product>();

    public void buyProduct(Product p)
    {
        boughtProducts.add(p);
    }

    public void printReceipt()
    {
        List<ReceiptLine> receipt = new ArrayList<ReceiptLine>();
        int total = 0;
        int price;
        for(List<Product> boughtProducts : boughtProduct)
        {
            price = SomeThirdPartyClass.calculatePrice(boughtProduct.getBarcode());
            System.out.println(boughtProduct + ": " + price);
            total += price;
        }

        System.out.println("TOTAL: " + total);
    }
}

The problem is that the prices are calculated by a third party system with an external library, so I don't know them and I find it difficult (if not impossible) to write the acceptance test using FIT. In a normal case I would do something like:

Shopping list (input):

 -------------------
| product's barcode |
 -------------------
| 111111111         |
 -------------------
| 123456789         |
 -------------------
| 987654321         |
 -------------------
| 999999999         |
 -------------------

Receipt (expected output):

 ------------------
| receipt          |
 ------------------
| 111111111: 1.99  |
 ------------------
| 123456789: 2.99  |
 ------------------
| 987654321: 3.99  |
 ------------------
| 999999999: 4.99  |
 ------------------
| TOTAL: 13.96     |
 ------------------

But how can I achieve this without knowing the prices? What's the best strategy to adopt? Is there any other framework to achieve this?

Thank you.

Update: The SomeThirdPartyClass is final, trying to mock it or to write a Proxy class for it will give the following error:

Cannot subclass final class class SomeThirdPartyClass

Furthermore, it's immutable and the public constructor has no arguments. Seems like the teacher made it on purpose....


Solution

  • You can write a Proxy class for the third party library, and then inject a fake version of the class into RecieptSystem. I recommend JUnit and Mockito for this, although there are other frameworks you can use.

    If you are only allowed to do end-to-end testing, you can try feeding it input and save the output and create a regression test based on that. Unless you have requirements for the program don't bother guessing what the output should be. Just capture it and turn it into a regression test so you can safely refactor.

    I've played around with Selenium and other acceptance testing frameworks, but they are usually overkill unless you need to hook a GUI. I would just use JUnit. FITnesse is an updated version of FIT by Uncle Bob you might check out.