All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tngtech.jgiven.annotation.Table Maven / Gradle / Ivy

There is a newer version: 1.3.1
Show newest version
package com.tngtech.jgiven.annotation;

import static com.tngtech.jgiven.annotation.Table.HeaderType.HORIZONTAL;

import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.tngtech.jgiven.format.table.DefaultRowFormatterFactory;
import com.tngtech.jgiven.format.table.DefaultTableFormatter;
import com.tngtech.jgiven.format.table.RowFormatterFactory;
import com.tngtech.jgiven.format.table.TableFormatterFactory;
import com.tngtech.jgiven.impl.util.AnnotationUtil;

/**
 * Marks the parameter of a step method as a data table. Such parameters are
 * represented as tables in the report.
 * 

* In principle, every object can be represented as a table. However, JGiven * treats certain types of objects in a special way. *

* If a parameter implements the {@link java.lang.Iterable} or is an instance of * an array then each element of the Iterable is interpreted as a single row of * the table. Otherwise JGiven will only create a single row. *

* The elements are again interpreted differently whether they are instances of * {@link java.lang.Iterable} or not. *

* If the elements are instances of Iterable then each element becomes a cell in * the row. Note that the first list is taken as the header of the table if the * {@link Table#columnTitles()} is not set. *

* If the elements are not instances of Iterable, the field names become the * headers and field values the data. This can be overridden by the * {@link #objectFormatting()} attribute. *

* It is also possible to completely replace the way JGiven translates arguments * to tables by using the {@link #formatter()} attribute *

*

Example

*

Some POJO

* *
 * {
 * 	@code
 * 	class CoffeeWithPrice {
 * 		String name;
 * 		double price_in_EUR;
 *
 * 		CoffeeWithPrice(String name, double priceInEur) {
 * 			this.name = name;
 * 			this.price_in_EUR = priceInEur;
 * 		}
 * 	}
 * }
 * 
* *

The Step Method

* *
 * {@code
 *     public SELF the_prices_of_the_coffees_are( @Table CoffeeWithPrice... prices ) {
 *         ...
 *     }
 * }
 * 
* *

Invocation of the step method

* *
 * {@code
 *     given().the_prices_of_the_coffees_are(
 *         new CoffeeWithPrice("Espresso", 2.0),
 *         new CoffeeWithPrice("Cappuccino", 2.5));
 * }
 * 
* *

Text Report

* *
 * {@code
 *     Given the prices of the coffees are
 *
 *          | name       | price in EUR |
 *          +------------+--------------+
 *          | Espresso   | 2.0          |
 *          | Cappuccino | 2.5          |
 *
 *
 * }
 * 
* * @since 0.6.1 */ @Documented @Retention( RetentionPolicy.RUNTIME ) @Target( { ElementType.PARAMETER, ElementType.ANNOTATION_TYPE } ) public @interface Table { /** * Specifies the header type of the table. Default is {@code HORIZONTAL}. *

* That is explained best by an example.
* Given the following table argument: * *

     * {@code new Object[][] {
     *     { "a1", "a2", "a3" },
     *     { "b1", "b2", "b3" },
     *     { "c1", "c2", "c3" }}
     * }
     * 
* * Then the header type argument has the following effect. *

{@code HeaderType.NONE}

This simply specifies the the table has * no header. The plain text report will produce the following output. * *
     *     | a1 | a2 | a3 |
     *     | b1 | b2 | b3 |
     *     | c1 | c2 | c3 |
     * 
* *

{@code HeaderType.HORIZONTAL}

Specifies that the first * row represents the header. * *
     *     | a1 | a2 | a3 |
     *     +----+----+----+
     *     | b1 | b2 | b3 |
     *     | c1 | c2 | c3 |
     * 
* *

{@code HeaderType.VERTICAL}

Specifies that the first * column represents the header. Thus elements a1, b1, and c1. The * plain text report will produce the same output as for header type NONE, * however, the HTML report will render the first column as a header. * *
     *     | a1 | a2 | a3 |
     *     | b1 | b2 | b3 |
     *     | c1 | c2 | c3 |
     * 
* *

{@code HeaderType.BOTH}

Specifies that the first row * and the first column are headers. The plain text report will * produce the same output as for header type HORIZONTAL, however, the HTML * report will render the first row and the first column as headers. * *
     *     | a1 | a2 | a3 |
     *     +----+----+----+
     *     | b1 | b2 | b3 |
     *     | c1 | c2 | c3 |
     * 
* *

Effect on POJO lists

When the data is given by a list of POJOs * then setting the header type to {@code VERTICAL} will also * transpose the table. For example *

* Given the following POJO list. * *

     * {@code new CoffeeWithPrice[] {
     *         new CoffeeWithPrice("Espresso", 2.0),
     *         new CoffeeWithPrice("Cappuccino", 2.5)}
     * }
     * 
* * When setting the header type to {@code VERTICAL}
* Then the report will present the following table * *
     * {@code
     *     | name         | Espresso | Cappuccino |
     *     | price in EUR | 2.0      | 2.5        |
     * }
     * 
*

* The header type {@code BOTH} cannot be applied to POJO lists *

* * @return the header type of the table. */ HeaderType header() default HORIZONTAL; /** * Whether to transpose the resulting table in the report or not. *

Example

Given the following data. * *
     * {@code new Object[][] {
     *     { "a1", "a2", "a3" },
     *     { "b1", "b2", "b3" },
     *     { "c1", "c2", "c3" }}
     * }
     * 
* * When transpose is set to {@code true} Then the table in the report will * look as follows: * *
     *     | a1 | b1 | c1 |
     *     +----+----+----+
     *     | a2 | b2 | c2 |
     *     | a3 | b3 | c3 |
     * 
* * instead of * *
     *     | a1 | a2 | a3 |
     *     +----+----+----+
     *     | b1 | b2 | b3 |
     *     | c1 | c2 | c3 |
     * 
*/ boolean transpose() default false; /** * Specifies which fields should be excluded in the report. *

* If {@link #includeFields()} is set, then this attribute has no effect * *

* Makes only sense when supplying a list of POJOs or a single POJO. */ String[] excludeFields() default {}; /** * Specifies which fields should be included in the report. * * All fields not in this list will be excluded. *

* Makes only sense when supplying a list of POJOs or a single POJO. */ String[] includeFields() default {}; /** * Explicitly specifies column titles of table header. *

* The first row of the data is not taken as the header row if this * attribute is set. *

* When a list of POJOs is given as parameter then this overrides the * default behavior of taking the field names as table headers. * *

Example

Given the following table argument: * *
     * {@code new Object[][] {
     *     { "a1", "a2", "a3" },
     *     { "b1", "b2", "b3" },
     *     { "c1", "c2", "c3" }}
     * }
     * 
* * Then the {@link #columnTitles()} attribute is set as follows: * *
     * columnTitles = { "t1", "t2", "t3" }
     * 
* * Then the resulting table will look as follows * *
     *     | t1 | t2 | t3 |
     *     +----+----+----+
     *     | a1 | a2 | a3 |
     *     | b1 | b2 | b3 |
     *     | c1 | c2 | c3 |
     * 
* * @since 0.7.1 */ String[] columnTitles() default {}; /** * Whether or not columns with only {@code null} values are shown or not. * Default is to not show them. * * @since 0.7.1 */ boolean includeNullColumns() default false; /** * Automatically number the rows of the table Default is not to generate * one. *

* If the table has a horizontal header, the generated column has header * '#'. To use a different header use {@link #numberedRowsHeader}. * * @since 0.8.2 */ boolean numberedRows() default false; /** * Like {@link #numberedRows} but specifies a different header for the * generated column. This implicitly sets {@see #numberedRows} to * {@code true}. *

* Note that in case the table has no horizontal header a * {@see JGivenWrongUsageException} will be thrown if this value is set. * * @since 0.8.2 */ String numberedRowsHeader() default AnnotationUtil.ABSENT; /** * Automatically number the columns of a table Default is not to generate * one. *

* If the table has a vertical header, the generated row has header '#'. To * use a different header use {@link #numberedColumnsHeader}. * * @since 0.8.2 */ boolean numberedColumns() default false; /** * Like {@link #numberedColumns} but specifies a different header for the * generated row. This implicitly sets {@see #numberedColumns} to * {@code true}. *

* Note that in case the table has no vertical header a * {@see JGivenWrongUsageException} will be thrown if this value is set. * * @since 0.8.2 */ String numberedColumnsHeader() default AnnotationUtil.ABSENT; public enum HeaderType { /** * The table has no header */ NONE, /** * Treat the first row as a header */ HORIZONTAL, /** * Treat the first column as a header */ VERTICAL, /** * Treat both, the first row and the first column as headers */ BOTH; public boolean isHorizontal() { return this == HORIZONTAL || this == BOTH; } public boolean isVertical() { return this == VERTICAL || this == BOTH; } } /** * The formatter to use to translate the parameter object to a table. If you * only want to override how POJOs are formatted you should use the * {@link #objectFormatting()} or {@link #rowFormatter()} attribute. * * @since 0.10.0 */ Class formatter() default DefaultTableFormatter.Factory.class; /** * How to format rows when the rows are plain Objects, i.e. no Iterables. * Note that this setting is ignored if a different {@link #rowFormatter()} * is set. In addition, JGiven will automatically switch to the * {@link com.tngtech.jgiven.annotation.Table.ObjectFormatting#PLAIN} * formatter when there is an additional formatting annotation besides the * {@code @Table} annotation. * * @since 0.10.0 */ ObjectFormatting objectFormatting() default ObjectFormatting.FIELDS; /** * Possible choices for the {@link #objectFormatting()} attribute. * * @since 0.10.0 */ public enum ObjectFormatting { /** * Each field of the object becomes a column in the table */ FIELDS, /** * There is only one column and the values are created by formatting * each Object using the standard JGiven formatting. */ PLAIN } /** * Specifies a factory to create a custom * {@link com.tngtech.jgiven.format.table.RowFormatter} that is used to * format POJOs each row of the table. *

* The default implementation evaluates the {@link #objectFormatting()} * attribute and creates a corresponding RowFormatter *

* * @since 0.10.0 */ Class rowFormatter() default DefaultRowFormatterFactory.class; /** * Specify a custom {@link NamedFormats} annotation * *

* The {@link NamedFormat} defined in this set will be used when formatting * POJOs fields.
*

* */ Class fieldsFormatSetAnnotation() default Annotation.class; /** * Specify an array of {@link NamedFormat} to use when formatting POJOs * fields. *

* When a {@link NamedFormat#name()} matches a field name, field value is * formatted using this {@link NamedFormat}. *

* *

* Note : when set, has precedence over {@link #fieldsFormatSetAnnotation()} *

* * @See {@link #fieldFormatSet()} */ NamedFormat[] fieldsFormat() default {}; }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy