SlideShare a Scribd company logo
1 of 44
Test-Driven Development
           of
      Xtext DSLs
        Moritz Eysholdt
we strive for...

...product quality   ...development speed


        features         fast

robustness                      agile

     correctness
without tests   with tests


add source code         easy          easy


 modify source
                        risky          safe
    code

application state
                        large         small
while debugging
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
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
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
JUnit 4
XtextRunner

         ParameterizedXtextRunner
Test...
  content assist                     validation rules
                         scoping
 quickfixes
               value conversion formatter
  parser/AST                              serializer
                       derived values
exported 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
                     derived
exported EObjects
                               semantic highlighting
               typesystem
 autoedit
                   code generator     interpreter
person Peter
person Frank knows Peter
person Peter
person Frank knows Peter




                           Model:
                           	   persons+=Person*;
                           	
                           Person:
                           	   'person' name=ID
                           	   ('knows' knows=[Person|ID])?;
test scoping

person Peter
person 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, Jack
person 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, 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;
    }
}
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;
    }
}
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;
    }
}
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;
    }
}
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;
    }
}
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;
    }
}
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
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
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
double click here
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!
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

More Related Content

What's hot

Deep dive into Xtext scoping local and global scopes explained
Deep dive into Xtext scoping local and global scopes explainedDeep dive into Xtext scoping local and global scopes explained
Deep dive into Xtext scoping local and global scopes explainedHolger Schill
 
05 junit
05 junit05 junit
05 junitmha4
 
Java 8 - Features Overview
Java 8 - Features OverviewJava 8 - Features Overview
Java 8 - Features OverviewSergii Stets
 
Javascript under the hood 2
Javascript under the hood 2Javascript under the hood 2
Javascript under the hood 2Thang Tran Duc
 
Py.test
Py.testPy.test
Py.testsoasme
 
Serializing EMF models with Xtext
Serializing EMF models with XtextSerializing EMF models with Xtext
Serializing EMF models with Xtextmeysholdt
 
Working with Methods in Java.pptx
Working with Methods in Java.pptxWorking with Methods in Java.pptx
Working with Methods in Java.pptxmaryansagsgao
 
Implicit parameters, when to use them (or not)!
Implicit parameters, when to use them (or not)!Implicit parameters, when to use them (or not)!
Implicit parameters, when to use them (or not)!Julien Truffaut
 
java 8 new features
java 8 new features java 8 new features
java 8 new features Rohit Verma
 
Building Your Own DSL with Xtext
Building Your Own DSL with XtextBuilding Your Own DSL with Xtext
Building Your Own DSL with XtextGlobalLogic Ukraine
 
Unit Testing And Mocking
Unit Testing And MockingUnit Testing And Mocking
Unit Testing And MockingJoe Wilson
 
clean code book summary - uncle bob - English version
clean code book summary - uncle bob - English versionclean code book summary - uncle bob - English version
clean code book summary - uncle bob - English versionsaber tabatabaee
 

What's hot (20)

Deep dive into Xtext scoping local and global scopes explained
Deep dive into Xtext scoping local and global scopes explainedDeep dive into Xtext scoping local and global scopes explained
Deep dive into Xtext scoping local and global scopes explained
 
Unit testing with java
Unit testing with javaUnit testing with java
Unit testing with java
 
05 junit
05 junit05 junit
05 junit
 
Java 8 - Features Overview
Java 8 - Features OverviewJava 8 - Features Overview
Java 8 - Features Overview
 
Clean Code
Clean CodeClean Code
Clean Code
 
Javascript under the hood 2
Javascript under the hood 2Javascript under the hood 2
Javascript under the hood 2
 
Py.test
Py.testPy.test
Py.test
 
Typescript ppt
Typescript pptTypescript ppt
Typescript ppt
 
Serializing EMF models with Xtext
Serializing EMF models with XtextSerializing EMF models with Xtext
Serializing EMF models with Xtext
 
Java 8 features
Java 8 featuresJava 8 features
Java 8 features
 
Clean code slide
Clean code slideClean code slide
Clean code slide
 
Introduction to java 8 stream api
Introduction to java 8 stream apiIntroduction to java 8 stream api
Introduction to java 8 stream api
 
Working with Methods in Java.pptx
Working with Methods in Java.pptxWorking with Methods in Java.pptx
Working with Methods in Java.pptx
 
Implicit parameters, when to use them (or not)!
Implicit parameters, when to use them (or not)!Implicit parameters, when to use them (or not)!
Implicit parameters, when to use them (or not)!
 
java 8 new features
java 8 new features java 8 new features
java 8 new features
 
Building Your Own DSL with Xtext
Building Your Own DSL with XtextBuilding Your Own DSL with Xtext
Building Your Own DSL with Xtext
 
Unit Testing And Mocking
Unit Testing And MockingUnit Testing And Mocking
Unit Testing And Mocking
 
Java keywords
Java keywordsJava keywords
Java keywords
 
clean code book summary - uncle bob - English version
clean code book summary - uncle bob - English versionclean code book summary - uncle bob - English version
clean code book summary - uncle bob - English version
 
TypeScript intro
TypeScript introTypeScript intro
TypeScript intro
 

Similar to Test-Driven Development of Xtext DSLs

Refactoring In Tdd The Missing Part
Refactoring In Tdd The Missing PartRefactoring In Tdd The Missing Part
Refactoring In Tdd The Missing PartGabriele Lana
 
15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)
15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)
15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)Danny Preussler
 
Test driven development - JUnit basics and best practices
Test driven development - JUnit basics and best practicesTest driven development - JUnit basics and best practices
Test driven development - JUnit basics and best practicesNarendra Pathai
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testingpleeps
 
Static code analysis: what? how? why?
Static code analysis: what? how? why?Static code analysis: what? how? why?
Static code analysis: what? how? why?Andrey Karpov
 
Atlassian Groovy Plugins
Atlassian Groovy PluginsAtlassian Groovy Plugins
Atlassian Groovy PluginsPaul King
 
Using xUnit as a Swiss-Aarmy Testing Toolkit
Using xUnit as a Swiss-Aarmy Testing ToolkitUsing xUnit as a Swiss-Aarmy Testing Toolkit
Using xUnit as a Swiss-Aarmy Testing ToolkitChris Oldwood
 
Testing And Drupal
Testing And DrupalTesting And Drupal
Testing And DrupalPeter Arato
 
Better Code through Lint and Checkstyle
Better Code through Lint and CheckstyleBetter Code through Lint and Checkstyle
Better Code through Lint and CheckstyleMarc Prengemann
 
Static analysis: Around Java in 60 minutes
Static analysis: Around Java in 60 minutesStatic analysis: Around Java in 60 minutes
Static analysis: Around Java in 60 minutesAndrey Karpov
 
Spock: Test Well and Prosper
Spock: Test Well and ProsperSpock: Test Well and Prosper
Spock: Test Well and ProsperKen Kousen
 
Attacks against Microsoft network web clients
Attacks against Microsoft network web clients Attacks against Microsoft network web clients
Attacks against Microsoft network web clients Positive Hack Days
 
Дмитрий Контрерас «Back to the future: the evolution of the Java Type System»
Дмитрий Контрерас «Back to the future: the evolution of the Java Type System»Дмитрий Контрерас «Back to the future: the evolution of the Java Type System»
Дмитрий Контрерас «Back to the future: the evolution of the Java Type System»Anna Shymchenko
 
Building a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to SpaceBuilding a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to SpaceMaarten Balliauw
 
Advances in Unit Testing: Theory and Practice
Advances in Unit Testing: Theory and PracticeAdvances in Unit Testing: Theory and Practice
Advances in Unit Testing: Theory and PracticeTao Xie
 
C# 6 and 7 and Futures 20180607
C# 6 and 7 and Futures 20180607C# 6 and 7 and Futures 20180607
C# 6 and 7 and Futures 20180607Kevin Hazzard
 

Similar to Test-Driven Development of Xtext DSLs (20)

Refactoring In Tdd The Missing Part
Refactoring In Tdd The Missing PartRefactoring In Tdd The Missing Part
Refactoring In Tdd The Missing Part
 
15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)
15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)
15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)
 
Tdd & unit test
Tdd & unit testTdd & unit test
Tdd & unit test
 
Test driven development - JUnit basics and best practices
Test driven development - JUnit basics and best practicesTest driven development - JUnit basics and best practices
Test driven development - JUnit basics and best practices
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testing
 
Static code analysis: what? how? why?
Static code analysis: what? how? why?Static code analysis: what? how? why?
Static code analysis: what? how? why?
 
Atlassian Groovy Plugins
Atlassian Groovy PluginsAtlassian Groovy Plugins
Atlassian Groovy Plugins
 
Using xUnit as a Swiss-Aarmy Testing Toolkit
Using xUnit as a Swiss-Aarmy Testing ToolkitUsing xUnit as a Swiss-Aarmy Testing Toolkit
Using xUnit as a Swiss-Aarmy Testing Toolkit
 
Testing And Drupal
Testing And DrupalTesting And Drupal
Testing And Drupal
 
Better Code through Lint and Checkstyle
Better Code through Lint and CheckstyleBetter Code through Lint and Checkstyle
Better Code through Lint and Checkstyle
 
Static analysis: Around Java in 60 minutes
Static analysis: Around Java in 60 minutesStatic analysis: Around Java in 60 minutes
Static analysis: Around Java in 60 minutes
 
Spock: Test Well and Prosper
Spock: Test Well and ProsperSpock: Test Well and Prosper
Spock: Test Well and Prosper
 
Attacks against Microsoft network web clients
Attacks against Microsoft network web clients Attacks against Microsoft network web clients
Attacks against Microsoft network web clients
 
Дмитрий Контрерас «Back to the future: the evolution of the Java Type System»
Дмитрий Контрерас «Back to the future: the evolution of the Java Type System»Дмитрий Контрерас «Back to the future: the evolution of the Java Type System»
Дмитрий Контрерас «Back to the future: the evolution of the Java Type System»
 
Building a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to SpaceBuilding a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to Space
 
Advances in Unit Testing: Theory and Practice
Advances in Unit Testing: Theory and PracticeAdvances in Unit Testing: Theory and Practice
Advances in Unit Testing: Theory and Practice
 
Junit_.pptx
Junit_.pptxJunit_.pptx
Junit_.pptx
 
Rc2010 tdd
Rc2010 tddRc2010 tdd
Rc2010 tdd
 
Full Text Search In PostgreSQL
Full Text Search In PostgreSQLFull Text Search In PostgreSQL
Full Text Search In PostgreSQL
 
C# 6 and 7 and Futures 20180607
C# 6 and 7 and Futures 20180607C# 6 and 7 and Futures 20180607
C# 6 and 7 and Futures 20180607
 

More from meysholdt

Xtext's new Formatter API
Xtext's new Formatter APIXtext's new Formatter API
Xtext's new Formatter APImeysholdt
 
Turning Ideas Into Code Faster
Turning Ideas Into Code FasterTurning Ideas Into Code Faster
Turning Ideas Into Code Fastermeysholdt
 
Executable specifications for xtext
Executable specifications for xtextExecutable specifications for xtext
Executable specifications for xtextmeysholdt
 
Xbase - Implementing Domain-Specific Languages for Java
Xbase - Implementing Domain-Specific Languages for JavaXbase - Implementing Domain-Specific Languages for Java
Xbase - Implementing Domain-Specific Languages for Javameysholdt
 
Codegeneration Goodies
Codegeneration GoodiesCodegeneration Goodies
Codegeneration Goodiesmeysholdt
 
Converging Textual and Graphical Editors
Converging Textual  and Graphical EditorsConverging Textual  and Graphical Editors
Converging Textual and Graphical Editorsmeysholdt
 

More from meysholdt (6)

Xtext's new Formatter API
Xtext's new Formatter APIXtext's new Formatter API
Xtext's new Formatter API
 
Turning Ideas Into Code Faster
Turning Ideas Into Code FasterTurning Ideas Into Code Faster
Turning Ideas Into Code Faster
 
Executable specifications for xtext
Executable specifications for xtextExecutable specifications for xtext
Executable specifications for xtext
 
Xbase - Implementing Domain-Specific Languages for Java
Xbase - Implementing Domain-Specific Languages for JavaXbase - Implementing Domain-Specific Languages for Java
Xbase - Implementing Domain-Specific Languages for Java
 
Codegeneration Goodies
Codegeneration GoodiesCodegeneration Goodies
Codegeneration Goodies
 
Converging Textual and Graphical Editors
Converging Textual  and Graphical EditorsConverging Textual  and Graphical Editors
Converging Textual and Graphical Editors
 

Recently uploaded

Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Victor Rentea
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfOverkill Security
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfOrbitshub
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistandanishmna97
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024The Digital Insurer
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024The Digital Insurer
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWERMadyBayot
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...apidays
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...Zilliz
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...apidays
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesrafiqahmad00786416
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusZilliz
 

Recently uploaded (20)

Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdf
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 

Test-Driven Development of Xtext DSLs

  • 1. Test-Driven Development of Xtext DSLs Moritz Eysholdt
  • 2. we strive for... ...product quality ...development speed features fast robustness agile correctness
  • 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
  • 7. JUnit 4 XtextRunner ParameterizedXtextRunner
  • 8. Test... content assist validation rules scoping quickfixes value conversion formatter parser/AST serializer derived values exported EObjects semantic highlighting typesystem autoedit code generator interpreter
  • 9. Test... content assist validation rules scoping quickfixes value conversion formatter your own code parser/AST serializer integration with framework the framework values derived exported EObjects semantic highlighting typesystem autoedit code generator interpreter
  • 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
  • 40.
  • 41.
  • 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

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n