2

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....

satoshi
  • 3,963
  • 6
  • 46
  • 57

1 Answers1

0

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.

Garrett Hall
  • 29,524
  • 10
  • 61
  • 76
  • Thanks, @GarrettHall. Exactly, that's what I would do in a real situation. But I'm not allowed to change the code in any way before writing any code (it's part of the homework requirements...) – satoshi Feb 27 '12 at 18:34
  • Then just capture the output then and create a regression test from that. FITnesse is an updated version of FIT you might want to check out, but JUnit should work fine. – Garrett Hall Feb 27 '12 at 18:44
  • I agree with @GarrettHall. You could use a mocking framework, like [Mockito](http://code.google.com/p/mockito/) to simulate the response from the 3rd party library. eg. `Mockito.when(SomeThirdPartyLibrary.calculatePrice("11111111")).thenReturn("1.99");` – radimpe Feb 27 '12 at 19:00
  • Ok, I was going to do it but I get an error because the class I'm trying to mock is declared as final ("Cannot subclass final class class SomeThirdPartyClass")... (updated the original question) – satoshi Feb 28 '12 at 21:32
  • Write a proxy for your third party class and mock it. Or use PowerMock. – Garrett Hall Feb 28 '12 at 22:52