testing xtext languages

53
Testing Xtext Languages Lorenzo Bettini Dipartimento di Informatica, Università di Torino, Italy itemis GmbH, Zurich, Switzerland EclipseCon France 2015 Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 1/43

Upload: ngodang

Post on 16-Dec-2016

266 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Testing Xtext Languages

Testing Xtext Languages

Lorenzo Bettini

Dipartimento di Informatica, Università di Torino, Italyitemis GmbH, Zurich, Switzerland

EclipseCon France 2015

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 1/43

Page 2: Testing Xtext Languages

Wrong Workflow

Modify the languageStart an Eclipse runtime instanceManually check that “everything” works in the editor

Write tests instead!

The example for this talkhttp://github.com/LorenzoBettini/ecefrance2015-xtext-example

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 2/43

Page 3: Testing Xtext Languages

Wrong Workflow

Modify the languageStart an Eclipse runtime instanceManually check that “everything” works in the editor

Write tests instead!

The example for this talkhttp://github.com/LorenzoBettini/ecefrance2015-xtext-example

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 2/43

Page 4: Testing Xtext Languages

Example DSL: simple expressionsWrite simple variables and expressions and generate Java code

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 3/43

Page 5: Testing Xtext Languages

Initial Grammar

grammar org.eclipsecon.expdsl.Expressions with org.eclipse.xtext.common.Terminals

generate expressions "http://www.eclipsecon.org/expdsl/Expressions"

ExpressionsModel:elements += AbstractElement*;

AbstractElement:Variable | Expression ;

Variable:declaredType=Type name=ID '=' expression=Expression;

Type:{IntType} 'int' |{BoolType} 'bool';

Expression:{IntConstant} value=INT |{StringConstant} value=STRING |{BoolConstant} value=('true'|'false') |{VariableRef} variable=[Variable];

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 4/43

Page 6: Testing Xtext Languages

Initial Problems: “left recursion”

SolutionApply Left Factoring techniqueBut let’s start testing right away!To check that we get associativity/priority right

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 5/43

Page 7: Testing Xtext Languages

Projects Structure

Xtext already generates a testing projectWith injector providers (headless and UI tests)

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 6/43

Page 8: Testing Xtext Languages

Junit tests

Most parts can be tested as Junit tests (no UI required)This is much faster!

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 7/43

Page 9: Testing Xtext Languages

Typical TestCase (Xtend)

Run with XtextRunnerInjectWith the generated injector providerInject Xtext testing utility classes

package org.eclipsecon.expdsl.tests

import static extension org.junit.Assert.*

@RunWith(typeof(XtextRunner))@InjectWith(typeof(ExpressionsInjectorProvider))class ExpressionsParserTest {

@Inject extension ParseHelper<ExpressionsModel>@Inject extension ValidationTestHelper

@Testdef void testSimpleExpression() {

"10".parse.assertNoErrors}

}

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 8/43

Page 10: Testing Xtext Languages

Testing the Parser

Tests that the program is parsed without syntax errorsTest that the AST is created as expected:

expected associativityexpected operator precedence

ParseHelper: parses a string and returns the AST

Additional BenefitsAfter parsing, the “real” language developer’s job starts:Validate the AST, generate code, etc.So it’s better that the AST is created the way you expect it

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 9/43

Page 11: Testing Xtext Languages

Testing the Parser

Tests that the program is parsed without syntax errorsTest that the AST is created as expected:

expected associativityexpected operator precedence

ParseHelper: parses a string and returns the AST

Additional BenefitsAfter parsing, the “real” language developer’s job starts:Validate the AST, generate code, etc.So it’s better that the AST is created the way you expect it

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 9/43

Page 12: Testing Xtext Languages

Testing the Parser

Given the AST we create a string representation thathighlights precedence/associativityCheck that it is as expected

def String stringRepr(Expression e) {switch (e) {

Plus: "(" + e.left.stringRepr+ " + " + e.right.stringRepr + ")"// other cases (omissis)Not: "!(" + e.expression.stringRepr ")"IntConstant: "" + e.value

}}

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 10/43

Page 13: Testing Xtext Languages

Testing the Parser

Given the AST we create a string representation thathighlights precedence/associativityCheck that it is as expected

def String stringRepr(Expression e) {switch (e) {

Plus: "(" + e.left.stringRepr+ " + " + e.right.stringRepr + ")"// other cases (omissis)Not: "!(" + e.expression.stringRepr ")"IntConstant: "" + e.value

}}

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 10/43

Page 14: Testing Xtext Languages

Testing the Parser

@Test def void testPlusMulPrecedence() {"10 + 5 * 2 - 5 / 1".assertRepr("((10 + (5 * 2)) - (5 / 1))")

}@Test def void testComparison() {

"10 <= 5 < 2 > 5".assertReprNoValidation("(((10 <= 5) < 2) > 5)")}@Test def void testEqualityAndComparison() {

"true == 5 <= 2".assertRepr("(true == (5 <= 2))")}@Test def void testAndOr() {

"true || false && 1 < 0".assertRepr("(true || (false && (1 < 0)))")}

def assertRepr(CharSequence input, CharSequence expected) {input.parse => [

expected.assertEquals((elements.last as Expression).stringRepr

)]

}

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 11/43

Page 15: Testing Xtext Languages

Validation

We want to avoid forward variable referencesint i = j // This should be an error!int j = 0

Let’s write a utility class, ExpressionsModelUtils, thatGiven any elementreturns the list of variable declared before(we have to walk in the AST model)

Let’s test such class separatelyi.e., before writing the validator itself

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 12/43

Page 16: Testing Xtext Languages

Validation

We want to avoid forward variable referencesint i = j // This should be an error!int j = 0

Let’s write a utility class, ExpressionsModelUtils, thatGiven any elementreturns the list of variable declared before(we have to walk in the AST model)

Let’s test such class separatelyi.e., before writing the validator itself

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 12/43

Page 17: Testing Xtext Languages

Testing Forward References

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 13/43

Page 18: Testing Xtext Languages

Let’s “code coverage” right away (Eclemma/Jacoco)

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 14/43

Page 19: Testing Xtext Languages

Let’s “code coverage” right away (Eclemma/Jacoco)

Even if it’s generated Java code (by Xtend)

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 15/43

Page 20: Testing Xtext Languages

Now we can write the Validator

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 16/43

Page 21: Testing Xtext Languages

Testing the Validator

And now we test that such error is correctly generatedOn the expected element of the program

We use the utility class ValidationTestHelperWe can do that headlessly:

There’s no need to run the workbench

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 17/43

Page 22: Testing Xtext Languages

Testing the Validator

We use the utility class ValidationTestHelper

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 18/43

Page 23: Testing Xtext Languages

Type System & Type Checking

Check that expressions are correct with respect to typessubexpressions of a multiplication are integerin a variable declaration, initialization expression can beassigned to the variable declared type…

Implement the type system and test itImplement type checking in the validator, using the typesystem, and test it(not shown here: please have a look at the code)

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 19/43

Page 24: Testing Xtext Languages

Code Generation

For each expdsl file we generate:A Java class with the same name of the expdsl file in thepackage expressionsWith an eval() method

For each variable declaration we generate a Java variabledeclarationFor each standalone expression we generate aSystem.out.println

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 20/43

Page 25: Testing Xtext Languages

Testing the Compiler

Add the dependency org.eclipse.xtext.xbase.junitAdd the dependency org.eclipse.jdt.coreUse CompilationTestHelperSmall pitfall: use a custom injector provider for missing GoogleGuice bindings expected by Xbase classes (see the code)

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 21/43

Page 26: Testing Xtext Languages

Testing the generated Java code is as expected

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 22/43

Page 27: Testing Xtext Languages

Testing the generated Java code is correct Java code

The test will fail if the generated Java code contains Javaerrors.

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 23/43

Page 28: Testing Xtext Languages

Testing the generated Java executes correctly

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 24/43

Page 29: Testing Xtext Languages

Testing UI

The content assistThe integration with the workbenchThe outline

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 25/43

Page 30: Testing Xtext Languages

Testing the Content Assist

Add the dependency org.eclipse.xtext.common.types.uiUse as base classo.e.x.xbase.junit.ui.AbstractContentAssistTestInject your test case with ExpressionsUiInjectorProvider

This must be run as a “Junit Plug-in Test”Set memory arguments in the launch configuration:-Xms256m -Xmx1024m -XX:MaxPermSize=256m

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 26/43

Page 31: Testing Xtext Languages

Testing the Content Assist

Add the dependency org.eclipse.xtext.common.types.uiUse as base classo.e.x.xbase.junit.ui.AbstractContentAssistTestInject your test case with ExpressionsUiInjectorProvider

This must be run as a “Junit Plug-in Test”Set memory arguments in the launch configuration:-Xms256m -Xmx1024m -XX:MaxPermSize=256m

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 26/43

Page 32: Testing Xtext Languages

Testing the Content Assist

Use as base classo.e.x.xbase.junit.ui.AbstractContentAssistTest

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 27/43

Page 33: Testing Xtext Languages

Testing the Content Assist

Use as base classo.e.x.xbase.junit.ui.AbstractContentAssistTest

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 27/43

Page 34: Testing Xtext Languages

Tweaking the Content Assist

Don’t propose forward references (e.g., i and j)Don’t propose references of the wrong type (e.g., s)

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 28/43

Page 35: Testing Xtext Languages

Testing the modified Content Assist

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 29/43

Page 36: Testing Xtext Languages

Testing the Workbench Integration

How is my DSL integrated with the workbench?Does a correct file lead to the generation of a Java file intosrc-gen folder?Does everything compile fine?We use

o.e.x.junit4.ui.AbstractWorkbenchTest as the baseclassutility methods from JavaProjectSetupUtil andIResourcesSetupUtilmethods for accessing programmatically the workbench (fromo.e.core.resources)

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 30/43

Page 37: Testing Xtext Languages

Testing the Workbench Integration

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 31/43

Page 38: Testing Xtext Languages

Outline

Let’s customize it like that

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 32/43

Page 39: Testing Xtext Languages

Outline

Let’s customize it like that

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 32/43

Page 40: Testing Xtext Languages

Testing the OutlineSee the code for AbstractOutlineWorkbenchTest

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 33/43

Page 41: Testing Xtext Languages

Required Time for Junit tests

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 34/43

Page 42: Testing Xtext Languages

Required Time for Junit Plug-in tests

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 35/43

Page 43: Testing Xtext Languages

Headless Build - No UI

Or use maven-surefire-plugin if you experience problems withthe classloader.

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 36/43

Page 44: Testing Xtext Languages

Headless Build - No UI

Or use maven-surefire-plugin if you experience problems withthe classloader.

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 36/43

Page 45: Testing Xtext Languages

Headless Build - UI

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 37/43

Page 46: Testing Xtext Languages

Testing other aspects

If some aspects are not covered by Xtext testing frameworkyou can have a look at Xtext sourcesand get some inspiration…

This is what I did for the outline tests

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 38/43

Page 47: Testing Xtext Languages

Other Testing Frameworks

Xpect: http://www.xpect-tests.orgSWTBot, RCP Testing Tool, Jubula for functional tests

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 39/43

Page 48: Testing Xtext Languages

Use CI, e.g., Jenkins

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 40/43

Page 49: Testing Xtext Languages

Use CI, e.g., Jenkins

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 41/43

Page 50: Testing Xtext Languages

…or Travis

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 42/43

Page 51: Testing Xtext Languages

Small Advertising O:-)http://www.packtpub.com/implementing-domain-specific-languages-with-xtext-and-xtend/book

An entire chapter on testing

Please evaluate this session

Thanks! and Questions?

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 43/43

Page 52: Testing Xtext Languages

Small Advertising O:-)http://www.packtpub.com/implementing-domain-specific-languages-with-xtext-and-xtend/book

An entire chapter on testing

Please evaluate this session

Thanks! and Questions?

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 43/43

Page 53: Testing Xtext Languages

Small Advertising O:-)http://www.packtpub.com/implementing-domain-specific-languages-with-xtext-and-xtend/book

An entire chapter on testing

Please evaluate this session

Thanks! and Questions?

Lorenzo Bettini Testing Xtext Languages EclipseCon France 2015 43/43