Hibernate.orgCommunity Documentation

Chapter 3. Installation

3.1. Obtaining the Software
3.2. The TCK Environment

This chapter explains how to obtain the TCK and supporting software and provides recommendations for how to install/extract it on your system.

You can obtain a release of the Bean Validation TCK project via the official Bean Validation home page. The Bean Validation TCK is distributed as a ZIP file, which contains the TCK artifacts (the test suite binary and source, the test suite descriptor, the audit source and report), the TCK library dependencies in /lib and documentation in /doc. The contents should look like:

artifacts/
changelog.txt
docs/
lib/
license.txt
setup-examples/
src/
readme.md

You can also download the source code from GitHub - https://github.com/beanvalidation/beanvalidation-tck.

The JSR 349 reference implementation (RI) project is named Hibernate Validator. You can obtain the Hibernate Validator release used as reference implementation from the Hibernate Validator download page.

Note

Hibernate Validator is not required for running the Bean Validation TCK, but it can be used as a reference for familiarizing yourself with the TCK before testing your own Bean Validation implementation.

The TCK requires the following two Java runtime environments:

You should refer to vendor instructions for how to install the runtime.

The rest of the TCK software can simply be extracted. It's recommended that you create a dedicated folder to hold all of the jsr349-related artifacts. This guide assumes the folder is called jsr349. Extract the src folder of the TCK distribution into a sub-folder named tck or use the following git commands:

git clone git://github.com/beanvalidation/beanvalidation-tck tck
git checkout 1.1.0.Final

You can also check out the full Hibernate Validator source into a subfolder ri. This will allow you to run the TCK against Hibernate Validator.

git clone git://github.com/hibernate/hibernate-validator.git ri
git checkout 5.0.0.Final

The resulting folder structure is shown here:

jsr349/
   ri/
   tck/

Now lets have a look at one concrete test of the TCK, namely ConstraintInheritanceTest (found in tck/tests/src/main/java/org/hibernate/beanvalidation/tck/tests/constraints/inheritance/ConstraintInheritanceTest.java):

package org.hibernate.beanvalidation.tck.tests.constraints.inheritance;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.validation.metadata.BeanDescriptor;
import javax.validation.metadata.ConstraintDescriptor;
import javax.validation.metadata.PropertyDescriptor;

import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.testng.Arquillian;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.test.audit.annotations.SpecAssertion;
import org.jboss.test.audit.annotations.SpecAssertions;
import org.jboss.test.audit.annotations.SpecVersion;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import org.hibernate.beanvalidation.tck.util.TestUtil;
import org.hibernate.beanvalidation.tck.util.shrinkwrap.WebArchiveBuilder;

import static org.hibernate.beanvalidation.tck.util.TestUtil.assertCorrectConstraintTypes;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;

/**
 * @author Hardy Ferentschik
 */
@SpecVersion(spec = "beanvalidation", version = "1.1.0")
public class ConstraintInheritanceTest extends Arquillian {

    private Validator validator;

    @Deployment
    public static WebArchive createTestArchive() {
        return new WebArchiveBuilder()
                .withTestClassPackage( ConstraintInheritanceTest.class )
                .build();
    }

    @BeforeMethod
    public void setupValidator() {
        validator = TestUtil.getValidatorUnderTest();
    }

    @Test
    @SpecAssertion(section = "4.3", id = "b")
    public void testConstraintsOnSuperClassAreInherited() {
        BeanDescriptor beanDescriptor = validator.getConstraintsForClass( Bar.class );

        String propertyName = "foo";
        assertTrue( beanDescriptor.getConstraintsForProperty( propertyName ) != null );
        PropertyDescriptor propDescriptor = beanDescriptor.getConstraintsForProperty( propertyName );

        Annotation constraintAnnotation = propDescriptor.getConstraintDescriptors()
                .iterator()
                .next().getAnnotation();
        assertTrue( constraintAnnotation.annotationType() == NotNull.class );
    }

    @Test
    @SpecAssertions({
            @SpecAssertion(section = "4.3", id = "a"),
            @SpecAssertion(section = "4.3", id = "b")
    })
    public void testConstraintsOnInterfaceAreInherited() {
        BeanDescriptor beanDescriptor = validator.getConstraintsForClass( Bar.class );

        String propertyName = "fubar";
        assertTrue( beanDescriptor.getConstraintsForProperty( propertyName ) != null );
        PropertyDescriptor propDescriptor = beanDescriptor.getConstraintsForProperty( propertyName );

        Annotation constraintAnnotation = propDescriptor.getConstraintDescriptors()
                .iterator()
                .next().getAnnotation();
        assertTrue( constraintAnnotation.annotationType() == NotNull.class );
    }

    @Test
    @SpecAssertions({
            @SpecAssertion(section = "4.3", id = "a"),
            @SpecAssertion(section = "4.3", id = "c")
    })
    public void testConstraintsOnInterfaceAndImplementationAddUp() {
        BeanDescriptor beanDescriptor = validator.getConstraintsForClass( Bar.class );

        String propertyName = "name";
        assertTrue( beanDescriptor.getConstraintsForProperty( propertyName ) != null );
        PropertyDescriptor propDescriptor = beanDescriptor.getConstraintsForProperty( propertyName );

        List<Class<? extends Annotation>> constraintTypes = getConstraintTypes( propDescriptor.getConstraintDescriptors() );

        assertEquals( constraintTypes.size(), 2 );
        assertTrue( constraintTypes.contains( DecimalMin.class ) );
        assertTrue( constraintTypes.contains( Size.class ) );
    }

    @Test
    @SpecAssertions({
            @SpecAssertion(section = "4.3", id = "a"),
            @SpecAssertion(section = "4.3", id = "c")
    })
    public void testConstraintsOnSuperAndSubClassAddUp() {
        BeanDescriptor beanDescriptor = validator.getConstraintsForClass( Bar.class );

        String propertyName = "lastName";
        assertTrue( beanDescriptor.getConstraintsForProperty( propertyName ) != null );
        PropertyDescriptor propDescriptor = beanDescriptor.getConstraintsForProperty( propertyName );

        List<Class<? extends Annotation>> constraintTypes = getConstraintTypes( propDescriptor.getConstraintDescriptors() );

        assertEquals( constraintTypes.size(), 2 );
        assertTrue( constraintTypes.contains( DecimalMin.class ) );
        assertTrue( constraintTypes.contains( Size.class ) );
    }

    @Test
    @SpecAssertion(section = "4.6", id = "a")
    public void testValidationConsidersConstraintsFromSuperTypes() {
        Set<ConstraintViolation<Bar>> violations = validator.validate( new Bar() );
        assertCorrectConstraintTypes(
                violations,
                DecimalMin.class, DecimalMin.class, ValidBar.class, //Bar
                NotNull.class, Size.class, ValidFoo.class, //Foo
                NotNull.class, Size.class, ValidFubar.class //Fubar
        );
    }

    private List<Class<? extends Annotation>> getConstraintTypes(Iterable<ConstraintDescriptor<?>> descriptors) {
        List<Class<? extends Annotation>> constraintTypes = new ArrayList<Class<? extends Annotation>>();

        for ( ConstraintDescriptor<?> constraintDescriptor : descriptors ) {
            constraintTypes.add( constraintDescriptor.getAnnotation().annotationType() );
        }

        return constraintTypes;
    }
}

Each test class is treated as an individual artifact (hence the @Deployment annotation on the class). In most tests the created artifact is a standard Web application Archive build via WebArchiveBuilder which in turn is a helper class of the TCK itself alleviating the creation of of the artifact. All methods annotated with @Test are actual tests which are getting run. Last but not least we see the use of the @SpecAssertion annotation which creates the link between the tck-audit.xml document and the actual test (see Section 1.1, “TCK Primer”).

Running the TCK against the Bean Validation RI (Hibernate Validator) and JBoss AS 7