This document discusses test-driven development for Xtext domain-specific languages. It recommends testing features like content assist, validation rules, scoping, quickfixes, parsing, serialization, code generation, and integration with frameworks. Tests should be fast, specific, efficient to write and maintain, and make failures self-explanatory. Both plain JUnit tests and plug-in JUnit tests are demonstrated.
3. without tests with tests
add source code easy easy
modify source
risky safe
code
application state
large small
while debugging
4. without tests with tests
add source code easy easy
modify source
risky safe
code
application state
large small
lots of redundancy
while debugging architecture may erode
maintenance increasingly difficult
5. without tests with tests
add source code easy easy
extracting small test + debugging
may be faster then
modify source debugging large scenario
risky safe
code
application state
large small
while debugging
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 experts
self-explanatory on failure! save time
11. person Peter
person Frank knows Peter
Model:
persons+=Person*;
Person:
'person' name=ID
('knows' knows=[Person|ID])?;
12. test scoping
person Peter
person Frank knows Peter
Model:
persons+=Person*;
Person:
'person' name=ID
('knows' knows=[Person|ID])?;
13. StringBuilder modelString = new StringBuilder();
modelString.append("person Petern");
modelString.append("person Frank knows Petern");
Model model = parseHelper.parse(modelString);
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. 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. @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. @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. @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. @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. @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. @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. @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. @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. @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. @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. @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. @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. @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. @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. person Peter
DSL-File
// XPECT elementsInScope at P|eter --> Frank, Peter, Jack
person Frank knows Peter
/* XPECT elementsInScope at P|eter ---
Frank, !Jim
--- */
person Jack knows Peter
31. person Peter
DSL-File
// XPECT elementsInScope at P|eter --> Frank, Peter, Jack
person 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. person Peter
// XPECT elementsInScope at P|eter --> Frank, Peter, Jack
person 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. person Peter
// XPECT elementsInScope at P|eter --> Frank, Peter, Jack
person 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. person Peter
// XPECT elementsInScope at P|eter --> Frank, Peter, Jack
person 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. person Peter
// XPECT elementsInScope at P|eter --> Frank, Peter, Jack
person 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. person Peter
// XPECT elementsInScope at P|eter --> Frank, Peter, Jack
person Frank knows Peter
/* XPECT elementsInScope at P|eter ---
Frank, !Jim Parameters
--- */ STRING, ID, INT, OFFSET
person 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. person Peter
// XPECT elementsInScope at P|eter --> Frank, Peter, Jack
person Frank knows Peter
/* XPECT elementsInScope at P|eter ---
Frank, !Jim Parameters
--- */ STRING, ID, INT, OFFSET
person 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. person Peter
// XPECT elementsInScope at P|eter --> Frank, Peter, Jack
person Frank knows Peter
/* XPECT elementsInScope at P|eter ---
Frank, !Jim Expectation
--- */ SingleLine/MultiLine
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;
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. person Peter
// XPECT elementsInScope at P|eter --> Frank, Peter, Jack
person Frank knows Peter
/* XPECT elementsInScope at P|eter ---
Frank, !Jim Expectation
--- */ SingleLine/MultiLine
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;
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
43. qualities - a retrospective
fast (depends on developer)
specific (depends on developer)
efficient to write
efficient to maintain
easy to read/understand
self-explanatory on failure!
44. 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, Berlin
Eclipse 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