/**
* Copyright (c) 2012 BMW Car IT and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.jnario.spec.tests.integration;
import com.google.inject.Inject;
import java.util.Arrays;
import org.eclipse.xtend2.lib.StringConcatenation;
import org.eclipse.xtext.xbase.lib.Extension;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import org.jnario.jnario.test.util.BehaviorExecutor;
import org.jnario.jnario.test.util.Helpers;
import org.jnario.jnario.test.util.SpecTestCreator;
import org.jnario.lib.Assert;
import org.jnario.lib.ExampleTable;
import org.jnario.lib.ExampleTableIterators;
import org.jnario.lib.Should;
import org.jnario.runner.CreateWith;
import org.jnario.runner.ExampleGroupRunner;
import org.jnario.runner.Named;
import org.jnario.runner.Order;
import org.jnario.spec.tests.integration.UsingTablesSpecExample;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Example tables are a great way to structure input and expected output data.
*/
@CreateWith(SpecTestCreator.class)
@Named("Using Tables")
@RunWith(ExampleGroupRunner.class)
@SuppressWarnings("all")
public class UsingTablesSpec {
@Inject
@Extension
@org.jnario.runner.Extension
public BehaviorExecutor _behaviorExecutor;
/**
* Examples are stored within a table. Assertions for the table's values are
* best implemented by iterating over each table row using `forEach`.
* Inside the procedure that is passed to `forEach`, each value in a row can be
* directly accessed by it's column's name making use of
* Xtend's [implicit 'it'](http://www.eclipse.org/xtend/documentation/index.html#closures).
* @filter('''|.executesSuccessfully)
*/
@Test
@Named("accessing values")
@Order(1)
public void _accessingValues() throws Exception {
StringConcatenation _builder = new StringConcatenation();
_builder.append("package bootstrap");
_builder.newLine();
_builder.newLine();
_builder.append("describe \"Example Tables\"{");
_builder.newLine();
_builder.append(" ");
_builder.newLine();
_builder.append(" ");
_builder.append("def myExamples{");
_builder.newLine();
_builder.append(" ");
_builder.append("| String input | String result | ");
_builder.newLine();
_builder.append(" ");
_builder.append("| \"Hello World\" | \"HELLO WORLD\" | ");
_builder.newLine();
_builder.append(" ");
_builder.append("| \"Hallo Welt\" | \"HALLO WELT\" |");
_builder.newLine();
_builder.append(" ");
_builder.append("} ");
_builder.newLine();
_builder.append(" ");
_builder.newLine();
_builder.append(" ");
_builder.append("fact \"can be accessed via the table name\"{");
_builder.newLine();
_builder.append(" ");
_builder.append("myExamples.forEach[ ");
_builder.newLine();
_builder.append(" ");
_builder.append("input.toUpperCase should be result");
_builder.newLine();
_builder.append(" ");
_builder.append("] ");
_builder.newLine();
_builder.append(" ");
_builder.append("}");
_builder.newLine();
_builder.append("}");
_builder.newLine();
this._behaviorExecutor.executesSuccessfully(_builder);
}
/**
* Naming an example table is optional. If no name is provided, the default name 'examples' will be used.
* @filter('''|.executesSuccessfully)
*/
@Test
@Named("Naming examples")
@Order(2)
public void _namingExamples() throws Exception {
StringConcatenation _builder = new StringConcatenation();
_builder.append("package bootstrap");
_builder.newLine();
_builder.newLine();
_builder.append("describe \"Example Tables\"{");
_builder.newLine();
_builder.append(" ");
_builder.newLine();
_builder.append(" ");
_builder.append("def{");
_builder.newLine();
_builder.append(" ");
_builder.append("| a | b | ");
_builder.newLine();
_builder.append(" ");
_builder.append("| 0 | 1 |");
_builder.newLine();
_builder.append(" ");
_builder.append("}");
_builder.newLine();
_builder.newLine();
_builder.append(" ");
_builder.append("fact \"name is optional\"{ ");
_builder.newLine();
_builder.append(" ");
_builder.append("examples should not be null");
_builder.newLine();
_builder.append(" ");
_builder.append("} ");
_builder.newLine();
_builder.append("} ");
_builder.newLine();
this._behaviorExecutor.executesSuccessfully(_builder);
}
/**
* Values in an example table can be arbitrary non-void expressions, for examples closures:
* @filter('''|.executesSuccessfully)
*/
@Test
@Named("Expressions in tables")
@Order(3)
public void _expressionsInTables() throws Exception {
StringConcatenation _builder = new StringConcatenation();
_builder.append("package bootstrap");
_builder.newLine();
_builder.newLine();
_builder.append("describe \"Example Tables\"{");
_builder.newLine();
_builder.append(" ");
_builder.newLine();
_builder.append(" ");
_builder.append("def myExampleWithClosures{");
_builder.newLine();
_builder.append(" ");
_builder.append("| input | operation | result |");
_builder.newLine();
_builder.append(" ");
_builder.append("| \"a\" | [String s | s.toUpperCase] | \"A\" |");
_builder.newLine();
_builder.append(" ");
_builder.append("| \"B\" | [String s | s.toLowerCase] | \"b\" | ");
_builder.newLine();
_builder.append(" ");
_builder.append("} ");
_builder.newLine();
_builder.newLine();
_builder.append(" ");
_builder.append("fact \"supports closures as values\"{ ");
_builder.newLine();
_builder.append(" ");
_builder.append("myExampleWithClosures.forEach[");
_builder.newLine();
_builder.append(" ");
_builder.append("operation.apply(input) should be result");
_builder.newLine();
_builder.append(" ");
_builder.append("]");
_builder.newLine();
_builder.append(" ");
_builder.append("} ");
_builder.newLine();
_builder.append("}");
_builder.newLine();
this._behaviorExecutor.executesSuccessfully(_builder);
}
/**
* It is also possible to call methods or reference fields from within a table.
* @filter('''|.executesSuccessfully)
*/
@Test
@Named("Referencing members")
@Order(4)
public void _referencingMembers() throws Exception {
StringConcatenation _builder = new StringConcatenation();
_builder.append("package bootstrap");
_builder.newLine();
_builder.newLine();
_builder.append("describe \"Example Tables\"{");
_builder.newLine();
_builder.append(" ");
_builder.newLine();
_builder.append(" ");
_builder.append("String field = \"Hello\"");
_builder.newLine();
_builder.newLine();
_builder.append(" ");
_builder.append("def method(){");
_builder.newLine();
_builder.append(" ");
_builder.append("\"World\"");
_builder.newLine();
_builder.append(" ");
_builder.append("} ");
_builder.newLine();
_builder.newLine();
_builder.append(" ");
_builder.append("def myExampleWithMemberCalls{");
_builder.newLine();
_builder.append(" ");
_builder.append("| input | result |");
_builder.newLine();
_builder.append(" ");
_builder.append("| field | \"Hello\" |");
_builder.newLine();
_builder.append(" ");
_builder.append("| method() | \"World\" | ");
_builder.newLine();
_builder.append(" ");
_builder.append("} ");
_builder.newLine();
_builder.append(" ");
_builder.newLine();
_builder.append(" ");
_builder.append("fact \"supports closures as values\"{ ");
_builder.newLine();
_builder.append(" ");
_builder.append("myExampleWithMemberCalls.forEach[");
_builder.newLine();
_builder.append(" ");
_builder.append("input should be result");
_builder.newLine();
_builder.append(" ");
_builder.append("] ");
_builder.newLine();
_builder.append(" ");
_builder.append("} ");
_builder.newLine();
_builder.append("}");
_builder.newLine();
this._behaviorExecutor.executesSuccessfully(_builder);
}
/**
* Jnario automatically infers the type of a column. It will use the
* common supertype of all expressions in a column.
* @filter('''|.executesSuccessfully)
*/
@Test
@Named("Column type inference")
@Order(5)
public void _columnTypeInference() throws Exception {
StringConcatenation _builder = new StringConcatenation();
_builder.append("package bootstrap");
_builder.newLine();
_builder.newLine();
_builder.append("import java.util.*");
_builder.newLine();
_builder.newLine();
_builder.append("describe \"Example Tables\"{");
_builder.newLine();
_builder.append(" ");
_builder.append("def examplesWithTypeInference{");
_builder.newLine();
_builder.append(" ");
_builder.append("| list |");
_builder.newLine();
_builder.append(" ");
_builder.append("| null |");
_builder.newLine();
_builder.append(" ");
_builder.append("| new ArrayList<String>() |");
_builder.newLine();
_builder.append(" ");
_builder.append("| new LinkedList<String>() |");
_builder.newLine();
_builder.append(" ");
_builder.append("} ");
_builder.newLine();
_builder.newLine();
_builder.append(" ");
_builder.append("fact \"computes the common super type\"{");
_builder.newLine();
_builder.append(" ");
_builder.append("examplesWithTypeInference.forEach[");
_builder.newLine();
_builder.append(" \t");
_builder.append("if(list != null){");
_builder.newLine();
_builder.append(" ");
_builder.append("assert list.empty // works only if the type of list has been inferred as List<String>");
_builder.newLine();
_builder.append(" \t");
_builder.append("}");
_builder.newLine();
_builder.append(" ");
_builder.append("]");
_builder.newLine();
_builder.append(" ");
_builder.append("}");
_builder.newLine();
_builder.append("} ");
_builder.newLine();
this._behaviorExecutor.executesSuccessfully(_builder);
}
/**
* It is also possible to explicitly define the type of a column.
* @filter('''|.executesSuccessfully)
*/
@Test
@Named("Specifying column types")
@Order(6)
public void _specifyingColumnTypes() throws Exception {
StringConcatenation _builder = new StringConcatenation();
_builder.append("import java.util.ArrayList");
_builder.newLine();
_builder.append("import java.util.LinkedList");
_builder.newLine();
_builder.newLine();
_builder.append("describe \"Example Tables\"{");
_builder.newLine();
_builder.append(" ");
_builder.append("def examplesWithType{");
_builder.newLine();
_builder.append(" ");
_builder.append("| Iterable<String> list |");
_builder.newLine();
_builder.append(" ");
_builder.append("| new ArrayList<String>() |");
_builder.newLine();
_builder.append(" ");
_builder.append("| new LinkedList<String>() |");
_builder.newLine();
_builder.append(" ");
_builder.append("}");
_builder.newLine();
_builder.append(" ");
_builder.newLine();
_builder.append(" ");
_builder.append("fact \"computes the common super type\"{");
_builder.newLine();
_builder.append(" ");
_builder.append("examplesWithType.forEach[");
_builder.newLine();
_builder.append(" ");
_builder.append("assert list.empty");
_builder.newLine();
_builder.append(" ");
_builder.append("]");
_builder.newLine();
_builder.append(" ");
_builder.append("}");
_builder.newLine();
_builder.append("}");
_builder.newLine();
this._behaviorExecutor.executesSuccessfully(_builder);
}
public ExampleTable<UsingTablesSpecExample> _initUsingTablesSpecExample() {
return ExampleTable.create("example",
Arrays.asList("value1", "value2", "sum"),
new UsingTablesSpecExample( Arrays.asList("1", "2", "3"), _initUsingTablesSpecExampleCell0(), _initUsingTablesSpecExampleCell1(), _initUsingTablesSpecExampleCell2()),
new UsingTablesSpecExample( Arrays.asList("4", "5", "7"), _initUsingTablesSpecExampleCell3(), _initUsingTablesSpecExampleCell4(), _initUsingTablesSpecExampleCell5()),
new UsingTablesSpecExample( Arrays.asList("7", "8", "14"), _initUsingTablesSpecExampleCell6(), _initUsingTablesSpecExampleCell7(), _initUsingTablesSpecExampleCell8())
);
}
protected ExampleTable<UsingTablesSpecExample> example = _initUsingTablesSpecExample();
public int _initUsingTablesSpecExampleCell0() {
return 1;
}
public int _initUsingTablesSpecExampleCell1() {
return 2;
}
public int _initUsingTablesSpecExampleCell2() {
return 3;
}
public int _initUsingTablesSpecExampleCell3() {
return 4;
}
public int _initUsingTablesSpecExampleCell4() {
return 5;
}
public int _initUsingTablesSpecExampleCell5() {
return 7;
}
public int _initUsingTablesSpecExampleCell6() {
return 7;
}
public int _initUsingTablesSpecExampleCell7() {
return 8;
}
public int _initUsingTablesSpecExampleCell8() {
return 14;
}
/**
* `ExampleTable#forEach` executes the passed in procedure for all table rows.
* It will generate an error message for all procedures that have failed with the reason why they failed.
*/
@Test
@Named("Error message")
@Order(7)
public void _errorMessage() throws Exception {
final Procedure1<Boolean> _function = new Procedure1<Boolean>() {
public void apply(final Boolean it) {
final Procedure1<UsingTablesSpecExample> _function = new Procedure1<UsingTablesSpecExample>() {
public void apply(final UsingTablesSpecExample it) {
int _value1 = it.getValue1();
int _value2 = it.getValue2();
int _plus = (_value1 + _value2);
int _sum = it.getSum();
Assert.assertTrue("\nExpected value1 + value2 => sum but"
+ "\n value1 + value2 is " + new org.hamcrest.StringDescription().appendValue(Integer.valueOf(_plus)).toString()
+ "\n value1 is " + new org.hamcrest.StringDescription().appendValue(_value1).toString()
+ "\n value2 is " + new org.hamcrest.StringDescription().appendValue(_value2).toString()
+ "\n sum is " + new org.hamcrest.StringDescription().appendValue(Integer.valueOf(_sum)).toString() + "\n", Should.<Integer>operator_doubleArrow(Integer.valueOf(_plus), Integer.valueOf(_sum)));
}
};
ExampleTableIterators.<UsingTablesSpecExample>forEach(UsingTablesSpec.this.example, _function);
}
};
String _errorMessage = Helpers.errorMessage(_function);
StringConcatenation _builder = new StringConcatenation();
_builder.append("example failed");
_builder.newLine();
_builder.newLine();
_builder.append(" ");
_builder.append("| value1 | value2 | sum |");
_builder.newLine();
_builder.append(" ");
_builder.append("| 1 | 2 | 3 | ✓");
_builder.newLine();
_builder.append(" ");
_builder.append("| 4 | 5 | 7 | ✘ (1)");
_builder.newLine();
_builder.append(" ");
_builder.append("| 7 | 8 | 14 | ✘ (2)");
_builder.newLine();
_builder.newLine();
_builder.append("(1) | 4 | 5 | 7 | ✘");
_builder.newLine();
_builder.append("java.lang.AssertionError: ");
_builder.newLine();
_builder.append("Expected value1 + value2 => sum but");
_builder.newLine();
_builder.append(" ");
_builder.append("value1 + value2 is <9>");
_builder.newLine();
_builder.append(" ");
_builder.append("value1 is <4>");
_builder.newLine();
_builder.append(" ");
_builder.append("value2 is <5>");
_builder.newLine();
_builder.append(" ");
_builder.append("sum is <7>");
_builder.newLine();
_builder.newLine();
_builder.append("(2) | 7 | 8 | 14 | ✘");
_builder.newLine();
_builder.append("java.lang.AssertionError: ");
_builder.newLine();
_builder.append("Expected value1 + value2 => sum but");
_builder.newLine();
_builder.append(" ");
_builder.append("value1 + value2 is <15>");
_builder.newLine();
_builder.append(" ");
_builder.append("value1 is <7>");
_builder.newLine();
_builder.append(" ");
_builder.append("value2 is <8>");
_builder.newLine();
_builder.append(" ");
_builder.append("sum is <14>");
Helpers.is(_errorMessage, _builder);
}
/**
* A table column with a single null value will be inferred to java.lang.Object.
*/
@Test
@Named("type inference uses null for one column with null value")
@Order(8)
public void _typeInferenceUsesNullForOneColumnWithNullValue() throws Exception {
StringConcatenation _builder = new StringConcatenation();
_builder.append("describe \"TableBug\" {");
_builder.newLine();
_builder.append(" ");
_builder.append("def gkzData {");
_builder.newLine();
_builder.append(" ");
_builder.append("| value |");
_builder.newLine();
_builder.append(" ");
_builder.append("| null |");
_builder.newLine();
_builder.append(" ");
_builder.append("}");
_builder.newLine();
_builder.append("}");
_builder.newLine();
this._behaviorExecutor.executesSuccessfully(_builder);
}
/**
* Primitives will be converted to their wrapper type if one cell is null.
*/
@Test
@Named("Primitives & null")
@Order(9)
public void _primitivesNull() throws Exception {
StringConcatenation _builder = new StringConcatenation();
_builder.append("describe \"TableBug\" {");
_builder.newLine();
_builder.append(" ");
_builder.append("def gkzData {");
_builder.newLine();
_builder.append(" ");
_builder.append("| value |");
_builder.newLine();
_builder.append(" ");
_builder.append("| null |");
_builder.newLine();
_builder.append(" ");
_builder.append("| 1 |");
_builder.newLine();
_builder.append(" ");
_builder.append("}");
_builder.newLine();
_builder.append("}");
_builder.newLine();
this._behaviorExecutor.executesSuccessfully(_builder);
}
}