Test-Driven Development           of      Xtext DSLs        Moritz Eysholdt
we strive for......product quality   ...development speed        features         fastrobustness                      agil...
without tests   with testsadd source code         easy          easy modify source                        risky          s...
without tests           with testsadd source code         easy                    easy modify source                      ...
without tests           with testsadd source code         easy                    easy                                    ...
qualities of (unit) tests                        fast   run them locally                    specific    avoid redundancy   ...
JUnit 4XtextRunner         ParameterizedXtextRunner
Test...  content assist                     validation rules                         scoping quickfixes               value...
Test...  content assist                    validation rules                         scoping quickfixes              value c...
person Peterperson Frank knows Peter
person Peterperson Frank knows Peter                           Model:                           	   persons+=Person*;     ...
test scopingperson Peterperson Frank knows Peter                           Model:                           	   persons+=P...
StringBuilder modelString = new StringBuilder();modelString.append("person Petern");modelString.append("person Frank knows...
StringBuilder modelString = new StringBuilder();modelString.append("person Petern");modelString.append("person Frank knows...
StringBuilder modelString = new StringBuilder();modelString.append("person Petern");modelString.append("person Frank knows...
@RunWith(XtextRunner.class)@InjectWith(TestDemoInjectorProvider.class)public class ScopingTestPlain {    @Inject private P...
@RunWith(XtextRunner.class)                                                                     JUnit 4 Runner@InjectWith(...
@RunWith(XtextRunner.class)                                                                      JUnit 4 Runner@InjectWith...
@RunWith(XtextRunner.class)                                                                      JUnit 4 Runner@InjectWith...
@RunWith(XtextRunner.class)                                                                       JUnit 4 Runner@InjectWit...
@RunWith(XtextRunner.class)                                                                       JUnit 4 Runner@InjectWit...
@RunWith(XtextRunner.class)                                                                       JUnit 4 Runner@InjectWit...
@RunWith(XtextRunner.class)@InjectWith(TestDemoInjectorProvider.class)public class ScopingTestPlain {    @Inject private P...
@RunWith(XtextRunner.class)@InjectWith(TestDemoInjectorProvider.class)public class ScopingTestPlain {    @Inject private P...
@RunWith(XtextRunner.class)@InjectWith(TestDemoInjectorProvider.class)public class ScopingTestPlain {    @Inject private P...
@RunWith(XtextRunner.class)@InjectWith(TestDemoInjectorProvider.class)public class ScopingTestPlain {    @Inject private P...
@RunWith(XtextRunner.class)                      @RunWith(typeof(XtextRunner))@InjectWith(TestDemoInjectorProvider.class) ...
@RunWith(XtextRunner.class)@InjectWith(TestDemoInjectorProvider.class)public class ScopingTestPlain {    @Inject private P...
@RunWith(XtextRunner.class)@InjectWith(TestDemoInjectorProvider.class)public class ScopingTestPlain {    @Inject private P...
person Peter                                                            DSL-File// XPECT elementsInScope at P|eter --> Fra...
person Peter                                                                                 DSL-File// XPECT elementsInSc...
person Peter// XPECT elementsInScope at P|eter --> Frank, Peter, Jackperson Frank knows Peter/* XPECT elementsInScope at P...
person Peter// XPECT elementsInScope at P|eter --> Frank, Peter, Jackperson Frank knows Peter/* XPECT elementsInScope at P...
person Peter// XPECT elementsInScope at P|eter --> Frank, Peter, Jackperson Frank knows Peter/* XPECT elementsInScope at P...
person Peter// XPECT elementsInScope at P|eter --> Frank, Peter, Jackperson Frank knows Peter/* XPECT elementsInScope at P...
person Peter// XPECT elementsInScope at P|eter --> Frank, Peter, Jackperson Frank knows Peter/* XPECT elementsInScope at P...
person Peter// XPECT elementsInScope at P|eter --> Frank, Peter, Jackperson Frank knows Peter/* XPECT elementsInScope at P...
person Peter// XPECT elementsInScope at P|eter --> Frank, Peter, Jackperson Frank knows Peter/* XPECT elementsInScope at P...
person Peter// XPECT elementsInScope at P|eter --> Frank, Peter, Jackperson Frank knows Peter/* XPECT elementsInScope at P...
double click here
qualities - a retrospective                        fast   (depends on developer)                    specific    (depends on...
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:3...
Test-Driven Development  of Xtext DSLs
Test-Driven Development  of Xtext DSLs
Upcoming SlideShare
Loading in...5
×

Test-Driven Development of Xtext DSLs

5,334
-1

Published on

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.


Published in: Technology
0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
5,334
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
80
Comments
0
Likes
6
Embeds 0
No embeds

No notes for slide
  • \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

    1. 1. Test-Driven Development of Xtext DSLs Moritz Eysholdt
    2. 2. we strive for......product quality ...development speed features fastrobustness agile correctness
    3. 3. without tests with testsadd source code easy easy modify source risky safe codeapplication state large smallwhile debugging
    4. 4. 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
    5. 5. 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
    6. 6. 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
    7. 7. JUnit 4XtextRunner ParameterizedXtextRunner
    8. 8. Test... content assist validation rules scoping quickfixes value conversion formatter parser/AST serializer derived valuesexported EObjects semantic highlighting typesystem autoedit code generator interpreter
    9. 9. 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
    10. 10. person Peterperson Frank knows Peter
    11. 11. person Peterperson Frank knows Peter Model: persons+=Person*; Person: person name=ID (knows knows=[Person|ID])?;
    12. 12. test scopingperson Peterperson Frank knows Peter Model: persons+=Person*; Person: person name=ID (knows knows=[Person|ID])?;
    13. 13. StringBuilder modelString = new StringBuilder();modelString.append("person Petern");modelString.append("person Frank knows Petern");Model model = parseHelper.parse(modelString);
    14. 14. 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);
    15. 15. 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);
    16. 16. @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); }}
    17. 17. @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); }}
    18. 18. @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); }}
    19. 19. @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); }}
    20. 20. @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); }}
    21. 21. @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); }}
    22. 22. @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
    23. 23. @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); }}
    24. 24. @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); }}
    25. 25. @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}
    26. 26. @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); }}
    27. 27. @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); }}
    28. 28. @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 }}
    29. 29. @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 }}
    30. 30. 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
    31. 31. 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; }}
    32. 32. 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; }}
    33. 33. 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; }}
    34. 34. 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; }}
    35. 35. 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; }}
    36. 36. 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; }}
    37. 37. 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
    38. 38. 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
    39. 39. 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
    40. 40. double click here
    41. 41. qualities - a retrospective fast (depends on developer) specific (depends on developer) efficient to write efficient to maintain easy to read/understandself-explanatory on failure!
    42. 42. 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
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×