Test-Driven Development  of Xtext DSLs
Upcoming SlideShare
Loading in...5
×
 

Test-Driven Development of Xtext DSLs

on

  • 4,521 views

As presented at the EclipseCon Europe 2011: ...

As presented at the EclipseCon Europe 2011:
http://www.eclipsecon.org/europe2011/sessions/test-driven-development-xtext-dsls

In the spirit of Test Driven Development (TDD), most people know that it is a good idea to have some tests for the code you have written. After all, you want your functionality to survive the next refactoring, right? Furthermore, you want a minimal application state when hunting down a bug, don’t you? The same applies when developing (infrastructure for) Domain Specific Languages with Xtext. During the last year, I came across several situations where people had a hard time with this. It boiled down to two questions:

What to test?
How to test?

In this talk I will point out the essential spots end elaborate when and how to test them. I will show

how testing can greatly enhance your understanding about what is going on inside the frameworks.
how tests and language specifications can converge.
how to achieve a great test coverage with less effort. After all, for some people testing is not their primary duty.
how Google Guice can be used include customized or mocked components into your test-setup.
how to parameterize JUnit4 tests with test specifications.
how a language such as Xtend can be advantageous to write tests.


Statistics

Views

Total Views
4,521
Views on SlideShare
4,506
Embed Views
15

Actions

Likes
3
Downloads
64
Comments
0

5 Embeds 15

http://a0.twimg.com 6
http://paper.li 5
https://twitter.com 2
https://twimg0-a.akamaihd.net 1
https://si0.twimg.com 1

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n

Test-Driven Development  of Xtext DSLs Test-Driven Development of Xtext DSLs Presentation Transcript

  • Test-Driven Development of Xtext DSLs Moritz Eysholdt
  • we strive for......product quality ...development speed features fastrobustness agile correctness
  • without tests with testsadd source code easy easy modify source risky safe codeapplication state large smallwhile debugging
  • without tests with testsadd source code easy easy modify source risky safe codeapplication state large small lots of redundancywhile debugging architecture may erode maintenance increasingly difficult
  • without tests with testsadd source code easy easy extracting small test + debugging may be faster then modify source debugging large scenario risky safe codeapplication state large smallwhile debugging
  • qualities of (unit) tests fast run them locally specific avoid redundancy efficient to write save time efficient to maintain expectations can change easy to read/understand involve domain expertsself-explanatory on failure! save time
  • JUnit 4XtextRunner ParameterizedXtextRunner
  • Test... content assist validation rules scoping quickfixes value conversion formatter parser/AST serializer derived valuesexported EObjects semantic highlighting typesystem autoedit code generator interpreter
  • Test... content assist validation rules scoping quickfixes value conversion formatter your own code parser/AST serializer integration with framework the framework values derivedexported EObjects semantic highlighting typesystem autoedit code generator interpreter
  • person Peterperson Frank knows Peter
  • person Peterperson Frank knows Peter Model: persons+=Person*; Person: person name=ID (knows knows=[Person|ID])?;
  • test scopingperson Peterperson Frank knows Peter Model: persons+=Person*; Person: person name=ID (knows knows=[Person|ID])?;
  • StringBuilder modelString = new StringBuilder();modelString.append("person Petern");modelString.append("person Frank knows Petern");Model model = parseHelper.parse(modelString);
  • StringBuilder modelString = new StringBuilder();modelString.append("person Petern");modelString.append("person Frank knows Petern");Model model = parseHelper.parse(modelString);Person peter = model.getPersons().get(0);EReference reference = TestDemoPackage.eINSTANCE.getPerson_Knows();IScope scope = scopeProvider.getScope(peter, reference);
  • StringBuilder modelString = new StringBuilder();modelString.append("person Petern");modelString.append("person Frank knows Petern");Model model = parseHelper.parse(modelString);Person peter = model.getPersons().get(0);EReference reference = TestDemoPackage.eINSTANCE.getPerson_Knows();IScope scope = scopeProvider.getScope(peter, reference);List<String> actualList = Lists.newArrayList();for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString());String actual = Joiner.on(", ").join(actualList);Assert.assertEquals("Peter, Frank", actual);
  • @RunWith(XtextRunner.class)@InjectWith(TestDemoInjectorProvider.class)public class ScopingTestPlain { @Inject private ParseHelper<Model> parseHelper; @Inject private IScopeProvider scopeProvider; @Test public void testScope1() throws Exception { StringBuilder modelString = new StringBuilder(); modelString.append("person Petern"); modelString.append("person Frank knows Petern"); Model model = parseHelper.parse(modelString); Person peter = model.getPersons().get(0); EReference reference = TestDemoPackage.eINSTANCE.getPerson_Knows(); IScope scope = scopeProvider.getScope(peter, reference); List<String> actualList = Lists.newArrayList(); for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); String actual = Joiner.on(", ").join(actualList); Assert.assertEquals("Peter, Frank", actual); }}
  • @RunWith(XtextRunner.class) JUnit 4 Runner@InjectWith(TestDemoInjectorProvider.class)public class ScopingTestPlain { @Inject private ParseHelper<Model> parseHelper; @Inject private IScopeProvider scopeProvider; @Test public void testScope1() throws Exception { StringBuilder modelString = new StringBuilder(); modelString.append("person Petern"); modelString.append("person Frank knows Petern"); Model model = parseHelper.parse(modelString); Person peter = model.getPersons().get(0); EReference reference = TestDemoPackage.eINSTANCE.getPerson_Knows(); IScope scope = scopeProvider.getScope(peter, reference); List<String> actualList = Lists.newArrayList(); for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); String actual = Joiner.on(", ").join(actualList); Assert.assertEquals("Peter, Frank", actual); }}
  • @RunWith(XtextRunner.class) JUnit 4 Runner@InjectWith(TestDemoInjectorProvider.class)public class ScopingTestPlain { @Inject private ParseHelper<Model> parseHelper; Google Guice Injector @Inject private IScopeProvider scopeProvider; Injected Instances @Test public void testScope1() throws Exception { StringBuilder modelString = new StringBuilder(); modelString.append("person Petern"); modelString.append("person Frank knows Petern"); Model model = parseHelper.parse(modelString); Person peter = model.getPersons().get(0); EReference reference = TestDemoPackage.eINSTANCE.getPerson_Knows(); IScope scope = scopeProvider.getScope(peter, reference); List<String> actualList = Lists.newArrayList(); for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); String actual = Joiner.on(", ").join(actualList); Assert.assertEquals("Peter, Frank", actual); }}
  • @RunWith(XtextRunner.class) JUnit 4 Runner@InjectWith(TestDemoInjectorProvider.class)public class ScopingTestPlain { @Inject private ParseHelper<Model> parseHelper; Google Guice Injector @Inject private IScopeProvider scopeProvider; Injected Instances @Test public void testScope1() throws Exception { StringBuilder modelString = new StringBuilder(); modelString.append("person Petern"); modelString.append("person Frank knows Petern"); Backups and Restores Model model = parseHelper.parse(modelString); EMF Registries Person peter = model.getPersons().get(0); EReference reference = TestDemoPackage.eINSTANCE.getPerson_Knows(); IScope scope = scopeProvider.getScope(peter, reference); List<String> actualList = Lists.newArrayList(); for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); String actual = Joiner.on(", ").join(actualList); Assert.assertEquals("Peter, Frank", actual); }}
  • @RunWith(XtextRunner.class) JUnit 4 Runner@InjectWith(TestDemoInjectorProvider.class)public class ScopingTestPlain { @Inject private ParseHelper<Model> parseHelper; Google Guice Injector @Inject private IScopeProvider scopeProvider; Injected Instances @Test public void testScope1() throws Exception { StringBuilder modelString = new StringBuilder(); modelString.append("person Petern"); modelString.append("person Frank knows Petern"); Backups and Restores Model model = parseHelper.parse(modelString); EMF Registries Person peter = model.getPersons().get(0); EReference reference = TestDemoPackage.eINSTANCE.getPerson_Knows(); IScope scope = scopeProvider.getScope(peter, reference); Plain JUnit Test: No OSGi List<String> actualList = Lists.newArrayList(); Injector via StandaloneSetup for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); String actual = Joiner.on(", ").join(actualList); Assert.assertEquals("Peter, Frank", actual); }}
  • @RunWith(XtextRunner.class) JUnit 4 Runner@InjectWith(TestDemoInjectorProvider.class)public class ScopingTestPlain { @Inject private ParseHelper<Model> parseHelper; Google Guice Injector @Inject private IScopeProvider scopeProvider; Injected Instances @Test public void testScope1() throws Exception { StringBuilder modelString = new StringBuilder(); modelString.append("person Petern"); modelString.append("person Frank knows Petern"); Backups and Restores Model model = parseHelper.parse(modelString); EMF Registries Person peter = model.getPersons().get(0); EReference reference = TestDemoPackage.eINSTANCE.getPerson_Knows(); IScope scope = scopeProvider.getScope(peter, reference); FAST! Plain JUnit Test: No OSGi List<String> actualList = Lists.newArrayList(); Injector via StandaloneSetup for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); String actual = Joiner.on(", ").join(actualList); Assert.assertEquals("Peter, Frank", actual); }}
  • @RunWith(XtextRunner.class) JUnit 4 Runner@InjectWith(TestDemoInjectorProvider.class)public class ScopingTestPlain { @Inject private ParseHelper<Model> parseHelper; Google Guice Injector @Inject private IScopeProvider scopeProvider; Injected Instances @Test public void testScope1() throws Exception { StringBuilder modelString = new StringBuilder(); modelString.append("person Petern"); modelString.append("person Frank knows Petern"); Backups and Restores Model model = parseHelper.parse(modelString); EMF Registries Person peter = model.getPersons().get(0); EReference reference = TestDemoPackage.eINSTANCE.getPerson_Knows(); IScope scope = scopeProvider.getScope(peter, reference); FAST! Plain JUnit Test: No OSGi List<String> actualList = Lists.newArrayList(); Injector via StandaloneSetup for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); String actual = Joiner.on(", ").join(actualList); Assert.assertEquals("Peter, Frank", actual); Plug-In JUnit Test: } Eclipse Headless or Workbench} Injector via Activator
  • @RunWith(XtextRunner.class)@InjectWith(TestDemoInjectorProvider.class)public class ScopingTestPlain { @Inject private ParseHelper<Model> parseHelper; @Inject private IScopeProvider scopeProvider; @Test public void testScope1() throws Exception { StringBuilder modelString = new StringBuilder(); modelString.append("person Petern"); modelString.append("person Frank knows Petern"); Model model = parseHelper.parse(modelString); Person peter = model.getPersons().get(0); EReference reference = TestDemoPackage.eINSTANCE.getPerson_Knows(); IScope scope = scopeProvider.getScope(peter, reference); List<String> actualList = Lists.newArrayList(); for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); String actual = Joiner.on(", ").join(actualList); Assert.assertEquals("Peter, Frank", actual); }}
  • @RunWith(XtextRunner.class)@InjectWith(TestDemoInjectorProvider.class)public class ScopingTestPlain { @Inject private ParseHelper<Model> parseHelper; @Inject private IScopeProvider scopeProvider; @Test public void testScope1() throws Exception { StringBuilder modelString = new StringBuilder(); modelString.append("person Petern"); Exchange Components: Customize InjectorProvider modelString.append("person Frank knows Petern"); Model model = parseHelper.parse(modelString); via Components are configured Google Guice Person peter = model.getPersons().get(0); EReference reference = TestDemoPackage.eINSTANCE.getPerson_Knows(); IScope scope = scopeProvider.getScope(peter, reference); List<String> actualList = Lists.newArrayList(); for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); String actual = Joiner.on(", ").join(actualList); Assert.assertEquals("Peter, Frank", actual); }}
  • @RunWith(XtextRunner.class)@InjectWith(TestDemoInjectorProvider.class)public class ScopingTestPlain { @Inject private ParseHelper<Model> parseHelper; @Inject private IScopeProvider scopeProvider; @Test public void testScope1() throws Exception { StringBuilder modelString = new StringBuilder(); modelString.append("person Petern"); Exchange Components: Customize InjectorProvider modelString.append("person Frank knows Petern"); Model model = parseHelper.parse(modelString); via Components are configured Google Guice Person peter = model.getPersons().get(0); EReference reference = TestDemoPackage.eINSTANCE.getPerson_Knows(); IScope scope = scopeProvider.getScope(peter, reference); List<String> actualList = Lists.newArrayList(); for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); Mocking Components vs. Reusing Components String actual = Joiner.on(", ").join(actualList); Integration tests don’t hurt when they’re Assert.assertEquals("Peter, Frank", actual); not fragile, but specific and fast } Reusing Parser+Linker is more convenient than creating models programmatically}
  • @RunWith(XtextRunner.class)@InjectWith(TestDemoInjectorProvider.class)public class ScopingTestPlain { @Inject private ParseHelper<Model> parseHelper; @Inject private IScopeProvider scopeProvider; @Test public void testScope1() throws Exception { StringBuilder modelString = new StringBuilder(); modelString.append("person Petern"); modelString.append("person Frank knows Petern"); Model model = parseHelper.parse(modelString); (XtextRunner) Person Java Example peter = model.getPersons().get(0); EReference reference = TestDemoPackage.eINSTANCE.getPerson_Knows(); IScope scope = scopeProvider.getScope(peter, reference); List<String> actualList = Lists.newArrayList(); for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); String actual = Joiner.on(", ").join(actualList); Assert.assertEquals("Peter, Frank", actual); }}
  • @RunWith(XtextRunner.class) @RunWith(typeof(XtextRunner))@InjectWith(TestDemoInjectorProvider.class) @InjectWith(typeof(TestDemoInjectorProvider))public class ScopingTestPlain { class ScopingTestXtend { @Inject private ParseHelper<Model> parseHelper; @Inject extension ParseHelper<Model> @Inject extension IScopeProvider @Inject private IScopeProvider scopeProvider; @Test @Test public void testScope1() throws Exception { def testScope1() { StringBuilder modelString model = val = new StringBuilder(); modelString.append("person Petern"); person Peter modelString.append("person Frank Frank knows Peter person knows Petern"); Model model = parseHelper.parse(modelString); .parse (XtextRunner) Person Java Example peter = model.getPersons().get(0); val scope = getScope(model.persons.head, eINSTANCE.person_Knows) EReference reference = TestDemoPackage.eINSTANCE.getPerson_Knows(); val actual = scope.allElements.map[name.toString].join(", ") IScope scope = scopeProvider.getScope(peter, reference); assertEquals("Peter, Frank", actual); List<String> actualList = Lists.newArrayList(); } for (IEObjectDescription desc : scope.getAllElements()) } actualList.add(desc.getName().toString()); String actual = Joiner.on(", ").join(actualList); Assert.assertEquals("Peter, Frank", actual); }}
  • @RunWith(XtextRunner.class)@InjectWith(TestDemoInjectorProvider.class)public class ScopingTestPlain { @Inject private ParseHelper<Model> parseHelper; Data Flow @Inject private IScopeProvider scopeProvider; @Test public void testScope1() throws Exception { StringBuilder modelString = new StringBuilder(); modelString.append("person Petern"); modelString.append("person Frank knows Petern"); Model model = parseHelper.parse(modelString); prepare Person peter = model.getPersons().get(0); EReference reference = TestDemoPackage.eINSTANCE.getPerson_Knows(); IScope scope = scopeProvider.getScope(peter, reference); List<String> actualList = Lists.newArrayList(); process for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); String actual = Joiner.on(", ").join(actualList); Assert.assertEquals("Peter, Frank", actual); compare }}
  • @RunWith(XtextRunner.class)@InjectWith(TestDemoInjectorProvider.class)public class ScopingTestPlain { @Inject private ParseHelper<Model> parseHelper; Data Flow @Inject private IScopeProvider scopeProvider; @Test public void testScope1() throws Exception { (DSL File) prepare IScope scope = scopeProvider.getScope(peter, reference); List<String> actualList = Lists.newArrayList(); process for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); (DSL File) compare }}
  • person Peter DSL-File// XPECT elementsInScope at P|eter --> Frank, Peter, Jackperson Frank knows Peter/* XPECT elementsInScope at P|eter --- Frank, !Jim--- */person Jack knows Peter
  • person Peter DSL-File// XPECT elementsInScope at P|eter --> Frank, Peter, Jackperson Frank knows Peter/* XPECT elementsInScope at P|eter --- Frank, !Jim--- */person Jack knows Peter@RunWith(ParameterizedXtextRunner.class)@InjectWith(TestDemoInjectorProvider.class) JUnit 4 Test@ResourceURIs(baseDir = "testdata/", fileExtensions = "testdemo")public class ScopingTestPlain { @InjectParameter private Offset offset; @Inject private IScopeProvider scopeProvider; beta @ParameterSyntax("(at offset=OFFSET)?") @XpectCommaSeparatedValues public Iterable<String> elementsInScope() throws Exception { Pair<EObject, EStructuralFeature> pair = offset.getEStructuralFeatureByParent(); IScope scope = scopeProvider.getScope(pair.getFirst(), (EReference) pair.getSecond()); List<String> actualList = Lists.newArrayList(); for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); return actualList; }}
  • person Peter// XPECT elementsInScope at P|eter --> Frank, Peter, Jackperson Frank knows Peter/* XPECT elementsInScope at P|eter --- Frank, !Jim--- */person Jack knows Peter@RunWith(ParameterizedXtextRunner.class)@InjectWith(TestDemoInjectorProvider.class)@ResourceURIs(baseDir = "testdata/", fileExtensions = "testdemo")public class ScopingTestPlain { @InjectParameter private Offset offset; @Inject private IScopeProvider scopeProvider; @ParameterSyntax("(at offset=OFFSET)?") @XpectCommaSeparatedValues public Iterable<String> elementsInScope() throws Exception { Pair<EObject, EStructuralFeature> pair = offset.getEStructuralFeatureByParent(); IScope scope = scopeProvider.getScope(pair.getFirst(), (EReference) pair.getSecond()); List<String> actualList = Lists.newArrayList(); for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); return actualList; }}
  • person Peter// XPECT elementsInScope at P|eter --> Frank, Peter, Jackperson Frank knows Peter/* XPECT elementsInScope at P|eter --- Frank, !Jim--- */person Jack knows Peter@RunWith(ParameterizedXtextRunner.class)@InjectWith(TestDemoInjectorProvider.class) JUnit 4 Runner@ResourceURIs(baseDir = "testdata/", fileExtensions = "testdemo")public class ScopingTestPlain { @InjectParameter private Offset offset; @Inject private IScopeProvider scopeProvider; @ParameterSyntax("(at offset=OFFSET)?") @XpectCommaSeparatedValues public Iterable<String> elementsInScope() throws Exception { Pair<EObject, EStructuralFeature> pair = offset.getEStructuralFeatureByParent(); IScope scope = scopeProvider.getScope(pair.getFirst(), (EReference) pair.getSecond()); List<String> actualList = Lists.newArrayList(); for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); return actualList; }}
  • person Peter// XPECT elementsInScope at P|eter --> Frank, Peter, Jackperson Frank knows Peter/* XPECT elementsInScope at P|eter --- Frank, !Jim--- */person Jack knows Peter@RunWith(ParameterizedXtextRunner.class)@InjectWith(TestDemoInjectorProvider.class) JUnit 4 Runner@ResourceURIs(baseDir = "testdata/", fileExtensions = "testdemo")public class ScopingTestPlain { @InjectParameter private Offset offset; @Inject private IScopeProvider scopeProvider; @ParameterSyntax("(at offset=OFFSET)?") Folder with DSL-Files @XpectCommaSeparatedValues public Iterable<String> elementsInScope() throws Exception { Pair<EObject, EStructuralFeature> pair = offset.getEStructuralFeatureByParent(); IScope scope = scopeProvider.getScope(pair.getFirst(), (EReference) pair.getSecond()); List<String> actualList = Lists.newArrayList(); for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); return actualList; }}
  • person Peter// XPECT elementsInScope at P|eter --> Frank, Peter, Jackperson Frank knows Peter/* XPECT elementsInScope at P|eter --- Tests as Comments Frank, !Jim--- */person Jack knows Peter@RunWith(ParameterizedXtextRunner.class)@InjectWith(TestDemoInjectorProvider.class) JUnit 4 Runner@ResourceURIs(baseDir = "testdata/", fileExtensions = "testdemo")public class ScopingTestPlain { @InjectParameter private Offset offset; @Inject private IScopeProvider scopeProvider; @ParameterSyntax("(at offset=OFFSET)?") Folder with DSL-Files @XpectCommaSeparatedValues public Iterable<String> elementsInScope() throws Exception { Pair<EObject, EStructuralFeature> pair = offset.getEStructuralFeatureByParent(); IScope scope = scopeProvider.getScope(pair.getFirst(), (EReference) pair.getSecond()); List<String> actualList = Lists.newArrayList(); for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); return actualList; }}
  • person Peter// XPECT elementsInScope at P|eter --> Frank, Peter, Jackperson Frank knows Peter/* XPECT elementsInScope at P|eter --- Frank, !Jim Parameters--- */ STRING, ID, INT, OFFSETperson Jack knows Peter@RunWith(ParameterizedXtextRunner.class)@InjectWith(TestDemoInjectorProvider.class)@ResourceURIs(baseDir = "testdata/", fileExtensions = "testdemo")public class ScopingTestPlain { @InjectParameter private Offset offset; Parameter Value @Inject private IScopeProvider scopeProvider; @ParameterSyntax("(at offset=OFFSET)?") Parameter Syntax @XpectCommaSeparatedValues public Iterable<String> elementsInScope() throws Exception { Pair<EObject, EStructuralFeature> pair = offset.getEStructuralFeatureByParent(); IScope scope = scopeProvider.getScope(pair.getFirst(), (EReference) pair.getSecond()); List<String> actualList = Lists.newArrayList(); for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); return actualList; }}
  • person Peter// XPECT elementsInScope at P|eter --> Frank, Peter, Jackperson Frank knows Peter/* XPECT elementsInScope at P|eter --- Frank, !Jim Parameters--- */ STRING, ID, INT, OFFSETperson Jack knows Peter@RunWith(ParameterizedXtextRunner.class)@InjectWith(TestDemoInjectorProvider.class)@ResourceURIs(baseDir = "testdata/", fileExtensions = "testdemo")public class ScopingTestPlain { @InjectParameter private Offset offset; Parameter Value @Inject private IScopeProvider scopeProvider; @ParameterSyntax("(at offset=OFFSET)?") Parameter Syntax @XpectCommaSeparatedValues public Iterable<String> elementsInScope() throws Exception { Pair<EObject, EStructuralFeature> pair = offset.getEStructuralFeatureByParent(); IScope scope = scopeProvider.getScope(pair.getFirst(), (EReference) pair.getSecond()); List<String> actualList = Lists.newArrayList(); for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); return actualList; Implicit/Explicit }} Parameters
  • person Peter// XPECT elementsInScope at P|eter --> Frank, Peter, Jackperson Frank knows Peter/* XPECT elementsInScope at P|eter --- Frank, !Jim Expectation--- */ SingleLine/MultiLineperson Jack knows Peter@RunWith(ParameterizedXtextRunner.class)@InjectWith(TestDemoInjectorProvider.class)@ResourceURIs(baseDir = "testdata/", fileExtensions = "testdemo")public class ScopingTestPlain { @InjectParameter private Offset offset; @Inject private IScopeProvider scopeProvider; Expectation Kind @Xpect, @XpectString, @ParameterSyntax("(at offset=OFFSET)?") @XpectLines @XpectCommaSeparatedValues public Iterable<String> elementsInScope() throws Exception { Pair<EObject, EStructuralFeature> pair = offset.getEStructuralFeatureByParent(); IScope scope = scopeProvider.getScope(pair.getFirst(), (EReference) pair.getSecond()); List<String> actualList = Lists.newArrayList(); for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); return actualList; }} Actual Value
  • person Peter// XPECT elementsInScope at P|eter --> Frank, Peter, Jackperson Frank knows Peter/* XPECT elementsInScope at P|eter --- Frank, !Jim Expectation--- */ SingleLine/MultiLineperson Jack knows Peter@RunWith(ParameterizedXtextRunner.class)@InjectWith(TestDemoInjectorProvider.class)@ResourceURIs(baseDir = "testdata/", fileExtensions = "testdemo")public class ScopingTestPlain { @InjectParameter private Offset offset; @Inject private IScopeProvider scopeProvider; Expectation Kind @Xpect, @XpectString, @ParameterSyntax("(at offset=OFFSET)?") @XpectLines @XpectCommaSeparatedValues public Iterable<String> elementsInScope() throws Exception { Pair<EObject, EStructuralFeature> pair = offset.getEStructuralFeatureByParent(); IScope scope = scopeProvider.getScope(pair.getFirst(), (EReference) pair.getSecond()); List<String> actualList = Lists.newArrayList(); for (IEObjectDescription desc : scope.getAllElements()) actualList.add(desc.getName().toString()); CaseSensitive? return actualList; WhitespaceSensitive? } Ordered?} Actual Value
  • double click here
  • qualities - a retrospective fast (depends on developer) specific (depends on developer) efficient to write efficient to maintain easy to read/understandself-explanatory on failure!
  • Eclipse DemoCamp November 2011 07.11.2011, 18:15 – 22:00 Uhr, Bonn 08.11.2011, 18:30 – 22:00 Uhr, Dresden 28.11.2011, 18:30 – 22:00 Uhr, BerlinEclipse based DSL Tooling - Meet the Experts 29.11.2011, 13:30 - 19:00 Uhr, Frankfurt a.M.Xcore: ECore meets Xtext (Ed Merks)Verteilte Modellierung mit CDO (Eike Stepper)Ein Jahr Xtext im Einsatz für HMI-Definition (Stefan Weise & Gerd Zanker)Embedded Software Engineering-Kongress 06.12.2011 - 08.12.2011, 09:00 – 18:00 Uhr, Sindelfingen