SlideShare a Scribd company logo
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

Unit testing with JUnit
Unit testing with JUnitUnit testing with JUnit
Unit testing with JUnit
Thomas Zimmermann
 
Как построить свой фреймворк для автотестов?
Как построить свой фреймворк для автотестов?Как построить свой фреймворк для автотестов?
Как построить свой фреймворк для автотестов?
Dmitry Buzdin
 
The Xtext Grammar Language
The Xtext Grammar LanguageThe Xtext Grammar Language
The Xtext Grammar Language
Dr. Jan Köhnlein
 
TDD - Test Driven Development
TDD - Test Driven DevelopmentTDD - Test Driven Development
TDD - Test Driven Development
Tung Nguyen Thanh
 
Karate for Complex Web-Service API Testing by Peter Thomas
Karate for Complex Web-Service API Testing by Peter ThomasKarate for Complex Web-Service API Testing by Peter Thomas
Karate for Complex Web-Service API Testing by Peter Thomas
intuit_india
 
Clean code and Code Smells
Clean code and Code SmellsClean code and Code Smells
Clean code and Code Smells
Mario Sangiorgio
 
API Test Automation Using Karate (Anil Kumar Moka)
API Test Automation Using Karate (Anil Kumar Moka)API Test Automation Using Karate (Anil Kumar Moka)
API Test Automation Using Karate (Anil Kumar Moka)
Peter Thomas
 
Easy tests with Selenide and Easyb
Easy tests with Selenide and EasybEasy tests with Selenide and Easyb
Easy tests with Selenide and Easyb
Iakiv Kramarenko
 
Postman & API Testing by Amber Race
Postman & API Testing by Amber RacePostman & API Testing by Amber Race
Postman & API Testing by Amber Race
Postman
 
Karate DSL
Karate DSLKarate DSL
Karate DSL
anil borse
 
Testing in-python-and-pytest-framework
Testing in-python-and-pytest-frameworkTesting in-python-and-pytest-framework
Testing in-python-and-pytest-framework
Arulalan T
 
Advanced Javascript
Advanced JavascriptAdvanced Javascript
Advanced JavascriptAdieu
 
Using Xcore with Xtext
Using Xcore with XtextUsing Xcore with Xtext
Using Xcore with Xtext
Holger Schill
 
Getting started with karate dsl
Getting started with karate dslGetting started with karate dsl
Getting started with karate dsl
Knoldus Inc.
 
TDD in Python With Pytest
TDD in Python With PytestTDD in Python With Pytest
TDD in Python With Pytest
Eddy Reyes
 
Domain-Driven-Design 정복기 2탄
Domain-Driven-Design 정복기 2탄Domain-Driven-Design 정복기 2탄
Domain-Driven-Design 정복기 2탄
Suhyeon Jo
 
Unit Testing
Unit TestingUnit Testing
Unit Testing
Scott Leberknight
 
Real world selenium resume which gets more job interviews
Real world selenium resume which gets more job interviewsReal world selenium resume which gets more job interviews
Real world selenium resume which gets more job interviews
ABSoft Trainings
 
Karate - powerful and simple framework for REST API automation testing
Karate - powerful and simple framework for REST API automation testingKarate - powerful and simple framework for REST API automation testing
Karate - powerful and simple framework for REST API automation testing
Roman Liubun
 

What's hot (20)

Unit testing with JUnit
Unit testing with JUnitUnit testing with JUnit
Unit testing with JUnit
 
Как построить свой фреймворк для автотестов?
Как построить свой фреймворк для автотестов?Как построить свой фреймворк для автотестов?
Как построить свой фреймворк для автотестов?
 
The Xtext Grammar Language
The Xtext Grammar LanguageThe Xtext Grammar Language
The Xtext Grammar Language
 
TDD - Test Driven Development
TDD - Test Driven DevelopmentTDD - Test Driven Development
TDD - Test Driven Development
 
Karate for Complex Web-Service API Testing by Peter Thomas
Karate for Complex Web-Service API Testing by Peter ThomasKarate for Complex Web-Service API Testing by Peter Thomas
Karate for Complex Web-Service API Testing by Peter Thomas
 
Clean code and Code Smells
Clean code and Code SmellsClean code and Code Smells
Clean code and Code Smells
 
API Test Automation Using Karate (Anil Kumar Moka)
API Test Automation Using Karate (Anil Kumar Moka)API Test Automation Using Karate (Anil Kumar Moka)
API Test Automation Using Karate (Anil Kumar Moka)
 
Easy tests with Selenide and Easyb
Easy tests with Selenide and EasybEasy tests with Selenide and Easyb
Easy tests with Selenide and Easyb
 
Postman & API Testing by Amber Race
Postman & API Testing by Amber RacePostman & API Testing by Amber Race
Postman & API Testing by Amber Race
 
Karate DSL
Karate DSLKarate DSL
Karate DSL
 
Testing in-python-and-pytest-framework
Testing in-python-and-pytest-frameworkTesting in-python-and-pytest-framework
Testing in-python-and-pytest-framework
 
Clean coding-practices
Clean coding-practicesClean coding-practices
Clean coding-practices
 
Advanced Javascript
Advanced JavascriptAdvanced Javascript
Advanced Javascript
 
Using Xcore with Xtext
Using Xcore with XtextUsing Xcore with Xtext
Using Xcore with Xtext
 
Getting started with karate dsl
Getting started with karate dslGetting started with karate dsl
Getting started with karate dsl
 
TDD in Python With Pytest
TDD in Python With PytestTDD in Python With Pytest
TDD in Python With Pytest
 
Domain-Driven-Design 정복기 2탄
Domain-Driven-Design 정복기 2탄Domain-Driven-Design 정복기 2탄
Domain-Driven-Design 정복기 2탄
 
Unit Testing
Unit TestingUnit Testing
Unit Testing
 
Real world selenium resume which gets more job interviews
Real world selenium resume which gets more job interviewsReal world selenium resume which gets more job interviews
Real world selenium resume which gets more job interviews
 
Karate - powerful and simple framework for REST API automation testing
Karate - powerful and simple framework for REST API automation testingKarate - powerful and simple framework for REST API automation testing
Karate - powerful and simple framework for REST API automation testing
 

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
 
Tdd & unit test
Tdd & unit testTdd & unit test
Tdd & unit test
GomathiNayagam S
 
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
Narendra Pathai
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testing
pleeps
 
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 Plugins
Paul 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 Toolkit
Chris Oldwood
 
Testing And Drupal
Testing And DrupalTesting And Drupal
Testing And Drupal
Peter Arato
 
Better Code through Lint and Checkstyle
Better Code through Lint and CheckstyleBetter Code through Lint and Checkstyle
Better Code through Lint and Checkstyle
Marc 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 minutes
Andrey Karpov
 
Spock: Test Well and Prosper
Spock: Test Well and ProsperSpock: Test Well and Prosper
Spock: Test Well and Prosper
Ken 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 Space
Maarten 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 Practice
Tao Xie
 
Junit_.pptx
Junit_.pptxJunit_.pptx
Junit_.pptx
Suman Sourav
 
Rc2010 tdd
Rc2010 tddRc2010 tdd
Rc2010 tdd
JasonOffutt
 
Full Text Search In PostgreSQL
Full Text Search In PostgreSQLFull Text Search In PostgreSQL
Full Text Search In PostgreSQL
Karwin Software Solutions LLC
 
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
Kevin 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
 

Recently uploaded

Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
Safe Software
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Inflectra
 
ODC, Data Fabric and Architecture User Group
ODC, Data Fabric and Architecture User GroupODC, Data Fabric and Architecture User Group
ODC, Data Fabric and Architecture User Group
CatarinaPereira64715
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
Product School
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
Product School
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
Product School
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance
 
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Tobias Schneck
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
91mobiles
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Product School
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
RTTS
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Product School
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
Paul Groth
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
DanBrown980551
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
Product School
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
Ralf Eggert
 
Search and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical FuturesSearch and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical Futures
Bhaskar Mitra
 

Recently uploaded (20)

Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
ODC, Data Fabric and Architecture User Group
ODC, Data Fabric and Architecture User GroupODC, Data Fabric and Architecture User Group
ODC, Data Fabric and Architecture User Group
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
 
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
 
Search and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical FuturesSearch and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical Futures
 

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