5

Any good software architects would be agree that when someone builds a new project from scratch, he mustn't carry about boundaries at the beginning (database, GUI, external services etc...) Indeed, he should construct heart of his software independently of any backend and think about them as just kind of "plugins" to the application.

TDD and acceptance testing promote that for each new feature:

  1. Write a failing acceptance test (end-to-end) for the feature
  2. Drive and complete your code design thanks to some unit tests
  3. Finished as soon as acceptance test passes.

However, a lot of articles explain that an acceptance test is a really really end-to-end test involving thus GUI (browser (using Selenium for instance) or some other interface).

Shouldn't Acceptance testing be based on the application's HEART and independent of any boundaries? It would force me to think about GUI for instance... :s

What is a good practice? Write two kind of Acceptance tests for each feature?: one for business logic and one ensuring that the GUI well works?

Mik378
  • 21,881
  • 15
  • 82
  • 180

1 Answers1

4

First let me suggest reading Growing Object-Oriented Software, Guided by Tests by Steve Freeman and Nat Pryce. It's by far the best software testing book I read so far. What's great about it is that the authors don't focus on dummy use cases like Calculator class and using TDD to test add(int, int) method. This is silly. Instead they build fully-functioning application with Swing interface, network connectivity via XMPP and quite a lot of business logic. Which brings us back to your question.

Authors of the book above use various techniques and tools but they keep TDD practices all the time. For unit tests they go for but for acceptance and integration tests they actually automate starting an application (GUI) and XMPP test server.

They managed to test-drive GUI tests by employing high separation between the test and GUI. You should hide your user interface (web, desktop, SOAP web service, etc.) behind an abstraction called driver. Your test interacts only with the driver using high level methods like placeOrder("Foo"). Each driver (BrowserDriver, SwingDriver) understand what that means and either browses your web page or clicks buttons on fat GUI.

If you can change your GUI without changing test but only by changing underlying driver - you got it right.

See also

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • Thanks Tomasz! Actually, I own this book but haven't finished yet :) I like the notion of "page object" you've mentionned. So to sum up, (before I reopen the book) acceptance test dealing with GUI would define a generic `Driver` (independent of any specific GUI) and this one could be injected by Spring for instance (instance of selenium driver for webapp). Thus, I give up the idea of a "low-level" acceptance test dealing directly with services or entities but rather defines a unique Acceptance test dealing with `Driver` interface for one feature. Does it make sense? – Mik378 Jan 20 '13 at 15:33
  • @Mik378; more or less. You'll get `SeleniumDriver implements Driver`. Spring (as much as I love it) is not necessary here. I believe the book will explain that in much greater detail and better than me. – Tomasz Nurkiewicz Jan 20 '13 at 15:49
  • 1
    I supposed a test defining a `driver` field and initialized through Spring by its own application-context.xml. Why Spring ? Because it could allow to keep tests untouched the day where we add another type of GUI => just changing the Spring's xml configuration file (http://roger-almeida.blogspot.fr/2012/01/page-object-pattern-webdriver-spring.html). By the way, thanks for your great answer :) – Mik378 Jan 20 '13 at 16:52