Concordion Acceptance Testing: Getting Started

Concordion Acceptance Testing: Getting Started

Concordion is a Java-based acceptance testing framework built around the idea of specification by example. Instead of writing tests in code or wiki tables, you write plain HTML documents that describe how the system should behave. The framework then binds those documents to Java fixture classes that execute the examples and produce annotated HTML reports showing which specs passed or failed.

This approach keeps non-technical stakeholders in the conversation. A product manager can read and edit a Concordion spec without touching Java. The developer writes the glue code. The result is a living document that serves as both specification and regression test.

Maven and Gradle Setup

Add Concordion to your project dependencies. For Maven:

<dependency>
    <groupId>org.concordion</groupId>
    <artifactId>concordion</artifactId>
    <version>2.2.0</version>
    <scope>test</scope>
</dependency>

For Gradle:

testImplementation 'org.concordion:concordion:2.2.0'

Concordion requires JUnit 4 on the classpath. JUnit 5 support exists via a separate extension, but the standard runner still targets JUnit 4.

By default, Concordion expects your HTML spec files to live under src/test/resources in a package structure that matches your fixture class. If your fixture is com.example.LoginTest, the spec file lives at src/test/resources/com/example/Login.html.

You can override the default spec location with the system property concordion.output.dir for the report output directory, and by placing specs in the classpath root if you adjust the runner configuration.

Your First Specification

Create src/test/resources/com/example/Greeting.html:

<html xmlns:concordion="http://www.concordion.org/2007/concordion">
<body>
<h1>Greeting Feature</h1>
<p>
  When a user named
  <span concordion:set="#name">Bob</span>
  logs in, the system greets them with
  <span concordion:assertEquals="greetingFor(#name)">Hello, Bob!</span>
</p>
</body>
</html>

The concordion:set command assigns the text content of the element to a variable. The concordion:assertEquals command calls a fixture method and compares the return value to the element's text content. If they match, the element is highlighted green in the output report. If they differ, it turns red and shows the actual value.

The Java Fixture Class

package com.example;

import org.concordion.integration.junit4.ConcordionRunner;
import org.junit.runner.RunWith;

@RunWith(ConcordionRunner.class)
public class GreetingTest {

    public String greetingFor(String name) {
        return "Hello, " + name + "!";
    }
}

The @RunWith(ConcordionRunner.class) annotation is the only Concordion-specific annotation required on a basic fixture. The class name must match the HTML file name without the extension. Method names in the spec map directly to public methods on the fixture class.

Run it like any JUnit test:

mvn test -Dtest=GreetingTest

HTML Output Reports

After the test run, Concordion writes an annotated copy of your HTML spec to the output directory (default: build/concordion or target/concordion). Open the file in a browser to see exactly which assertions passed and which failed, with actual vs expected values shown inline.

This output is shareable. Drop the HTML file into a wiki or email it to a product manager and they can read the results without knowing anything about JUnit or Maven.

A More Complete Example

Here is a spec that tests a simple calculation:

<html xmlns:concordion="http://www.concordion.org/2007/concordion">
<body>
<h2>Order Total Calculation</h2>
<p>
  An order with
  <span concordion:set="#quantity">3</span> items
  at <span concordion:set="#price">25</span> each
  has a total of
  <span concordion:assertEquals="totalFor(#quantity, #price)">75</span>.
</p>
</body>
</html>

The fixture:

@RunWith(ConcordionRunner.class)
public class OrderTest {

    public int totalFor(int quantity, int price) {
        return quantity * price;
    }
}

Notice that Concordion automatically coerces the string values from the HTML into int parameters. It handles String, primitive numeric types, and their boxed equivalents without any explicit conversion.

Project Structure Recap

src/
  test/
    java/
      com/example/
        GreetingTest.java
        OrderTest.java
    resources/
      com/example/
        Greeting.html
        Order.html

Keep this parallel structure consistent. A mismatch between the package and the resource path is the most common setup error for new Concordion projects.

Next Step

Once your first spec runs and the output report opens in a browser, explore concordion:execute for calling methods that do not return a value, and concordion:verifyRows for asserting over collections. Both are covered in the specification commands reference.

Read more

Start now free