diff --git a/build.gradle b/build.gradle
index b500675302032e9d073e9b004158bd60ef888ab8..a82d2d7079fcd0f5ccd4192d1665ce807b200fd0 100644
--- a/build.gradle
+++ b/build.gradle
@@ -153,6 +153,13 @@ test.dependsOn compileRelationTest
 compileRelationTest.dependsOn doublePreprocessRelationTest
 doublePreprocessRelationTest.dependsOn preprocessRelationTest
 
+task compileConstructorTest(type: RelastTest) {
+    relastFiles 'src/test/jastadd/constructors/Constructors.relast'
+    grammarName = 'src/test/jastadd/constructors/Constructors'
+    packageName = 'constructors.ast'
+    moreInputFiles 'src/test/jastadd/constructors/Constructors.jrag'
+}
+
 task compileDefaultNamesTest(type: RelastTest) {
     relastFiles 'src/test/jastadd/relations/Relations.relast'
     grammarName = 'src/test/jastadd/relations/Relations3'
@@ -247,7 +254,6 @@ task compileSerializerDefaultNamesTest(type: RelastTest) {
 }
 
 task compileSerializerPointerTest(type: RelastTest) {
-    verbose = true
     resolverHelper = true
     relastFiles 'src/test/jastadd/serializer-pointer/Serializer.relast'
     grammarName = 'src/test/jastadd/serializer-pointer/Serializer'
@@ -257,7 +263,6 @@ task compileSerializerPointerTest(type: RelastTest) {
 }
 
 task compileSerializerManualTest(type: RelastTest) {
-    verbose = true
     resolverHelper = true
     relastFiles 'src/test/jastadd/serializer-manual/Serializer.relast'
     grammarName = 'src/test/jastadd/serializer-manual/Serializer'
@@ -267,7 +272,6 @@ task compileSerializerManualTest(type: RelastTest) {
 }
 
 task compileSerializerManualRelativeTest(type: RelastTest) {
-    verbose = true
     resolverHelper = true
     relastFiles 'src/test/jastadd/serializer-manual-relative/Serializer.relast'
     grammarName = 'src/test/jastadd/serializer-manual-relative/Serializer'
diff --git a/src/main/jastadd/Analysis.jrag b/src/main/jastadd/Analysis.jrag
index 27f3a7d89731f351b8a21043e9b2a816cd3d3548..139bd082748e4407dbdcbf851f54a8147fba7949 100644
--- a/src/main/jastadd/Analysis.jrag
+++ b/src/main/jastadd/Analysis.jrag
@@ -105,6 +105,11 @@ aspect ComponentAnalysis {
   //--- isEqual ---
   syn boolean Component.isEqual(Component c) = this.getClass() == c.getClass() && getTypeUse().isEqual(c.getTypeUse());
 
+  /**
+   * TokenComponents may be specialized by NTATokenComponents and vice versa
+   */
+  eq TokenComponent.isEqual(Component c) = (c instanceof TokenComponent) && getTypeUse().isEqual(c.getTypeUse());
+
   syn boolean TypeUse.isEqual(TypeUse u);
   eq SimpleTypeUse.isEqual(TypeUse u) = u instanceof SimpleTypeUse && getID().equals(u.getID());
   eq ParameterizedTypeUse.isEqual(TypeUse u) {
@@ -228,17 +233,7 @@ aspect Constructors {
   }
 
   //--- needsConstructor ---
-  syn boolean TypeDecl.needsConstructor() {
-    if (componentsTransitive().isEmpty()) {
-      return false;
-    }
-    if (!relationComponents().isEmpty()) {
-      return true;
-    }
-    return hasSuper()
-      && getSuper().decl() != null
-      && getSuper().decl().needsConstructor();
-  }
+  syn boolean TypeDecl.needsConstructor() = !componentsTransitive().isEmpty() && !relationComponentsTransitive().isEmpty();
 
   //--- inConstructor ---
   /**
@@ -248,6 +243,7 @@ aspect Constructors {
   eq NTAComponent.inConstructor() = false;
   eq NTAOptComponent.inConstructor() = false;
   eq NTAListComponent.inConstructor() = false;
+  eq NTATokenComponent.inConstructor() = false;
 }
 
 aspect Utils {
diff --git a/src/main/jastadd/Backend.jadd b/src/main/jastadd/Backend.jadd
index 26591c03e65af7dd169b1ec4e54bd0798e5d3dc1..cab17e15766bc3323d2cc8b6c1b8f5c3c754c396 100644
--- a/src/main/jastadd/Backend.jadd
+++ b/src/main/jastadd/Backend.jadd
@@ -111,6 +111,9 @@ aspect BackendAbstractGrammar {
   public String TokenComponent.generateAbstractGrammar() {
     return "<" + getID() + ":" + getTypeUse() + ">";
   }
+  public String NTATokenComponent.generateAbstractGrammar() {
+    return "/<" + getID() + ":" + getTypeUse() + ">/";
+  }
 
   public String RelationComponent.generateAbstractGrammar() {
     return "<" + getImplAttributeName() + ":" + ofTypeDecl() + ">";
diff --git a/src/main/jastadd/RelAst.ast b/src/main/jastadd/RelAst.ast
index f0132fc4b3a4c32f1e2f49aad19382dc64379dcf..31083b99eda970809f5f61e6e44a8e4fb23d1a68 100644
--- a/src/main/jastadd/RelAst.ast
+++ b/src/main/jastadd/RelAst.ast
@@ -11,6 +11,7 @@ NTAComponent : SimpleTypeComponent;
 NTAOptComponent : SimpleTypeComponent;
 NTAListComponent : SimpleTypeComponent;
 TokenComponent : Component ::= TypeUse;
+NTATokenComponent : TokenComponent ::= TypeUse;
 
 abstract TypeUse ::= <ID>;
 SimpleTypeUse : TypeUse;
diff --git a/src/main/jastadd/RelAst.flex b/src/main/jastadd/RelAst.flex
index 17049259871bf75b47bc9c5a2ef9d5a4fb4d9932..7c06485cec6e976d9297ac752ce4146c35c3ab4e 100644
--- a/src/main/jastadd/RelAst.flex
+++ b/src/main/jastadd/RelAst.flex
@@ -37,7 +37,7 @@ import org.jastadd.relast.parser.RelAstParser.Terminals;
 
 WhiteSpace = [ ] | \t | \f | \n | \r | \r\n
 TraditionalComment   = [/][*][^*]*[*]+([^*/][^*]*[*]+)*[/]
-EndOfLineComment = "//" [^\n|\r|\r\n]*
+EndOfLineComment = "//" [^\n\r]*
 Comment = {TraditionalComment} | {EndOfLineComment}
 
 ID = [a-zA-Z$_][a-zA-Z0-9$_]*
diff --git a/src/main/jastadd/RelAst.parser b/src/main/jastadd/RelAst.parser
index 6b138b97d35b76583a3226b376613b8316a95a36..32236a483b646c518fd69c9fc383c9ec594bc09c 100644
--- a/src/main/jastadd/RelAst.parser
+++ b/src/main/jastadd/RelAst.parser
@@ -34,9 +34,16 @@ SimpleTypeUse s_type_use =
   ID {: return new SimpleTypeUse(ID); :}
   ;
 
+ArrayList inner_type_use
+    = ID
+    | inner_type_use DOT ID
+    ;
+
 TypeUse type_use =
-    s_type_use.u                {: return u; :}
-  | parameterized_type_use.p    {: return p; :}
+//    s_type_use.u                {: return u; :}
+//  |
+  parameterized_type_use.p    {: return p; :}
+  | inner_type_use.p            {: return new SimpleTypeUse((String)p.stream().map( x -> ((Symbol)x).value.toString()).collect(java.util.stream.Collectors.joining("."))); :}
   ;
 ParameterizedTypeUse parameterized_type_use =
   ID LT type_use_list.l GT      {: return new ParameterizedTypeUse(ID, l); :}
@@ -63,11 +70,11 @@ Component component =
   | ID COL s_type_use.u STAR                  {: return new ListComponent(ID, u); :}
   | s_type_use.u STAR                         {: return new ListComponent(u.getID(), u); :}
   // Opt
-  | LBRACKET ID COL s_type_use.u RBRACKET {: return new OptComponent(ID, u); :}
-  | LBRACKET s_type_use.u RBRACKET {: return new OptComponent(u.getID(), u); :}
+  | LBRACKET ID COL s_type_use.u RBRACKET     {: return new OptComponent(ID, u); :}
+  | LBRACKET s_type_use.u RBRACKET            {: return new OptComponent(u.getID(), u); :}
   // NTA list
-  | SLASH ID COL s_type_use.u STAR SLASH {: return new NTAListComponent(ID, u); :}
-  | SLASH s_type_use.u STAR SLASH {: return new NTAListComponent(u.getID(), u); :}
+  | SLASH ID COL s_type_use.u STAR SLASH      {: return new NTAListComponent(ID, u); :}
+  | SLASH s_type_use.u STAR SLASH             {: return new NTAListComponent(u.getID(), u); :}
   // NTA opt
   | SLASH LBRACKET ID COL s_type_use.u RBRACKET SLASH {: return new NTAOptComponent(ID, u); :}
   | SLASH LBRACKET s_type_use.u RBRACKET SLASH {: return new NTAOptComponent(u.getID(), u); :}
@@ -75,8 +82,8 @@ Component component =
   | SLASH ID COL s_type_use.u SLASH           {: return new NTAComponent(ID, u); :}
   | SLASH s_type_use.u SLASH                  {: return new NTAComponent(u.getID(), u); :}
   // NTA Token (same as NTA)
-  | SLASH LT ID COL s_type_use.u GT SLASH     {: return new NTAComponent(ID, u); :}
-  | SLASH LT s_type_use.u GT SLASH            {: return new NTAComponent(u.getID(), u); :}
+  | SLASH LT ID COL s_type_use.u GT SLASH     {: return new NTATokenComponent(ID, u); :}
+  | SLASH LT ID GT SLASH                      {: return new NTATokenComponent(ID, new SimpleTypeUse("String")); :}
   // Token
   | LT ID COL type_use.u GT                   {: return new TokenComponent(ID, u); :}
   | LT ID GT                                  {: return new TokenComponent(ID, new SimpleTypeUse("String")); :}
diff --git a/src/test/jastadd/constructors/Constructors.jrag b/src/test/jastadd/constructors/Constructors.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..fd86b7f2f08d915ae6cc20a90de2383e5ae5fb44
--- /dev/null
+++ b/src/test/jastadd/constructors/Constructors.jrag
@@ -0,0 +1,13 @@
+aspect NTAs {
+  syn A S.getS4() = new A();
+  syn List<A> S.getS5List() = new List<>();
+  syn Opt<A> S.getS6Opt() = new Opt<>();
+  syn String S.getS7() = "";
+  syn long S.getS8() = 1L;
+
+  syn A B.getB4() = new A();
+  syn List<A> B.getB5List() = new List<>();
+  syn Opt<A> B.getB6Opt() = new Opt<>();
+  syn String B.getB7() = "";
+  syn long B.getB8() = 1L;
+}
diff --git a/src/test/jastadd/constructors/Constructors.relast b/src/test/jastadd/constructors/Constructors.relast
new file mode 100644
index 0000000000000000000000000000000000000000..5b3d5a9eda5af27ecaef5382c3d83fb65ee3a7cf
--- /dev/null
+++ b/src/test/jastadd/constructors/Constructors.relast
@@ -0,0 +1,9 @@
+A;
+S ::= S1:A S2:A* [S3:A] /S4:A/ /S5:A*/ /[S6:A]/ /<S7>/ /<S8:long>/;
+B : S ::= B1:A B2:A* [B3:A] /B4:A/ /B5:A*/ /[B6:A]/ /<B7>/ /<B8:long>/;
+X;
+Y;
+
+rel A.r1 -> X;
+rel S.r2* <-> Y.r2;
+rel B.r3? -> X;
diff --git a/src/test/jastadd/errors/Inheritance.expected b/src/test/jastadd/errors/Inheritance.expected
index b3382e004ae6e15ca9bbd1ed6695ece0e3110fbe..29ee61a9bffb84a9cbd5f05b874b5cdc88819446 100644
--- a/src/test/jastadd/errors/Inheritance.expected
+++ b/src/test/jastadd/errors/Inheritance.expected
@@ -1,3 +1,64 @@
 Errors:
 $FILENAME Line 4, column 12: Token 'X' is an invalid redefinition for type 'B3', conflicts with supertype 'A'
-$FILENAME Line 7, column 5: Role 'X' is an invalid redefinition for type 'B2', conflicts with supertype 'A'
+$FILENAME Line 4, column 23: Token 'MyName' is an invalid redefinition for type 'B3', conflicts with supertype 'A'
+
+$FILENAME Line 11, column 5: Role 'X' is an invalid redefinition for type 'B2', conflicts with supertype 'A'
+$FILENAME Line 12, column 5: Role 'X' is an invalid redefinition for type 'B2', conflicts with supertype 'A'
+$FILENAME Line 13, column 5: Role 'X' is an invalid redefinition for type 'B2', conflicts with supertype 'A'
+$FILENAME Line 14, column 5: Role 'X' is an invalid redefinition for type 'B2', conflicts with supertype 'A'
+$FILENAME Line 15, column 5: Role 'X' is an invalid redefinition for type 'B2', conflicts with supertype 'A'
+$FILENAME Line 16, column 5: Role 'X' is an invalid redefinition for type 'B2', conflicts with supertype 'A'
+$FILENAME Line 12, column 5: Role 'X' is already declared for type 'B2'
+$FILENAME Line 13, column 5: Role 'X' is already declared for type 'B2'
+$FILENAME Line 14, column 5: Role 'X' is already declared for type 'B2'
+$FILENAME Line 15, column 5: Role 'X' is already declared for type 'B2'
+$FILENAME Line 16, column 5: Role 'X' is already declared for type 'B2'
+
+$FILENAME Line 18, column 5: Role 'MyName' is an invalid redefinition for type 'B2', conflicts with supertype 'A'
+$FILENAME Line 19, column 5: Role 'MyName' is an invalid redefinition for type 'B2', conflicts with supertype 'A'
+$FILENAME Line 20, column 5: Role 'MyName' is an invalid redefinition for type 'B2', conflicts with supertype 'A'
+$FILENAME Line 21, column 5: Role 'MyName' is an invalid redefinition for type 'B2', conflicts with supertype 'A'
+$FILENAME Line 22, column 5: Role 'MyName' is an invalid redefinition for type 'B2', conflicts with supertype 'A'
+$FILENAME Line 23, column 5: Role 'MyName' is an invalid redefinition for type 'B2', conflicts with supertype 'A'
+$FILENAME Line 19, column 5: Role 'MyName' is already declared for type 'B2'
+$FILENAME Line 20, column 5: Role 'MyName' is already declared for type 'B2'
+$FILENAME Line 21, column 5: Role 'MyName' is already declared for type 'B2'
+$FILENAME Line 22, column 5: Role 'MyName' is already declared for type 'B2'
+$FILENAME Line 23, column 5: Role 'MyName' is already declared for type 'B2'
+
+$FILENAME Line 28, column 12: Token 'X' is an invalid redefinition for type 'D3', conflicts with supertype 'C'
+$FILENAME Line 30, column 5: Role 'X' is an invalid redefinition for type 'D2', conflicts with supertype 'C'
+$FILENAME Line 31, column 5: Role 'X' is an invalid redefinition for type 'D2', conflicts with supertype 'C'
+$FILENAME Line 32, column 5: Role 'X' is an invalid redefinition for type 'D2', conflicts with supertype 'C'
+$FILENAME Line 33, column 5: Role 'X' is an invalid redefinition for type 'D2', conflicts with supertype 'C'
+$FILENAME Line 34, column 5: Role 'X' is an invalid redefinition for type 'D2', conflicts with supertype 'C'
+$FILENAME Line 35, column 5: Role 'X' is an invalid redefinition for type 'D2', conflicts with supertype 'C'
+$FILENAME Line 31, column 5: Role 'X' is already declared for type 'D2'
+$FILENAME Line 32, column 5: Role 'X' is already declared for type 'D2'
+$FILENAME Line 33, column 5: Role 'X' is already declared for type 'D2'
+$FILENAME Line 34, column 5: Role 'X' is already declared for type 'D2'
+$FILENAME Line 35, column 5: Role 'X' is already declared for type 'D2'
+
+$FILENAME Line 37, column 5: Role 'MyName' is an invalid redefinition for type 'D2', conflicts with supertype 'C'
+$FILENAME Line 38, column 5: Role 'MyName' is an invalid redefinition for type 'D2', conflicts with supertype 'C'
+$FILENAME Line 39, column 5: Role 'MyName' is an invalid redefinition for type 'D2', conflicts with supertype 'C'
+$FILENAME Line 40, column 5: Role 'MyName' is an invalid redefinition for type 'D2', conflicts with supertype 'C'
+$FILENAME Line 41, column 5: Role 'MyName' is an invalid redefinition for type 'D2', conflicts with supertype 'C'
+$FILENAME Line 42, column 5: Role 'MyName' is an invalid redefinition for type 'D2', conflicts with supertype 'C'
+$FILENAME Line 38, column 5: Role 'MyName' is already declared for type 'D2'
+$FILENAME Line 39, column 5: Role 'MyName' is already declared for type 'D2'
+$FILENAME Line 40, column 5: Role 'MyName' is already declared for type 'D2'
+$FILENAME Line 41, column 5: Role 'MyName' is already declared for type 'D2'
+$FILENAME Line 42, column 5: Role 'MyName' is already declared for type 'D2'
+
+$FILENAME Line 44, column 5: Role 'X2' is an invalid redefinition for type 'D2', conflicts with supertype 'C'
+$FILENAME Line 45, column 5: Role 'X2' is an invalid redefinition for type 'D2', conflicts with supertype 'C'
+$FILENAME Line 46, column 5: Role 'X2' is an invalid redefinition for type 'D2', conflicts with supertype 'C'
+$FILENAME Line 47, column 5: Role 'X2' is an invalid redefinition for type 'D2', conflicts with supertype 'C'
+$FILENAME Line 48, column 5: Role 'X2' is an invalid redefinition for type 'D2', conflicts with supertype 'C'
+$FILENAME Line 49, column 5: Role 'X2' is an invalid redefinition for type 'D2', conflicts with supertype 'C'
+$FILENAME Line 45, column 5: Role 'X2' is already declared for type 'D2'
+$FILENAME Line 46, column 5: Role 'X2' is already declared for type 'D2'
+$FILENAME Line 47, column 5: Role 'X2' is already declared for type 'D2'
+$FILENAME Line 48, column 5: Role 'X2' is already declared for type 'D2'
+$FILENAME Line 49, column 5: Role 'X2' is already declared for type 'D2'
diff --git a/src/test/jastadd/errors/Inheritance.relast b/src/test/jastadd/errors/Inheritance.relast
index db746eb173254ba6c28d7bb2d585b1c92f7e76f3..e8529a8be66598c2d56fddd38dd15c66d1f732e5 100644
--- a/src/test/jastadd/errors/Inheritance.relast
+++ b/src/test/jastadd/errors/Inheritance.relast
@@ -1,7 +1,49 @@
-A ::= X;
-B1 : A ::= X;
+A ::= X MyName:X;
+B1 : A ::= X MyName:X MyName:Y;
 B2 : A;
-B3 : A ::= <X:String>;
+B3 : A ::= <X:String> <MyName:String>;
+// B4 has a child named X of type SubX
+B4 : A ::= X:SubX;
 X;
+SubX : X;
+Y;
 
 rel B2.X -> X;
+rel B2.X -> Y;
+rel B2.X? -> X;
+rel B2.X? -> Y;
+rel B2.X* -> X;
+rel B2.X* -> Y;
+
+rel B2.MyName -> X;
+rel B2.MyName -> Y;
+rel B2.MyName? -> X;
+rel B2.MyName? -> Y;
+rel B2.MyName* -> X;
+rel B2.MyName* -> Y;
+
+C ::= /X/ /MyName:X/ /<X2:long>/ ;
+D1 : C ::= X;
+D2 : C;
+D3 : C ::= <X:String> ;
+
+rel D2.X -> X;
+rel D2.X -> Y;
+rel D2.X? -> X;
+rel D2.X? -> Y;
+rel D2.X* -> X;
+rel D2.X* -> Y;
+
+rel D2.MyName -> X;
+rel D2.MyName -> Y;
+rel D2.MyName? -> X;
+rel D2.MyName? -> Y;
+rel D2.MyName* -> X;
+rel D2.MyName* -> Y;
+
+rel D2.X2 -> X;
+rel D2.X2 -> Y;
+rel D2.X2? -> X;
+rel D2.X2? -> Y;
+rel D2.X2* -> X;
+rel D2.X2* -> Y;
diff --git a/src/test/jastadd/relations/Relations.relast b/src/test/jastadd/relations/Relations.relast
index bdcc87885ae227cfd2d384659a8d1d535ee63aa0..498e4fcf2553c37020ae9b53e64b3cd0f5703fb7 100644
--- a/src/test/jastadd/relations/Relations.relast
+++ b/src/test/jastadd/relations/Relations.relast
@@ -41,3 +41,23 @@ rel A <- Root.AaLeft?;
 rel B <- A.Di1Left ;
 rel B <- A.Di2Left?;
 rel B <- A.Di3Left*;
+
+// empty productions
+C ;
+
+// production with nonterminals of different kinds
+D ::= SingleA:A ListOfA:A* [OptionalA:A] /NTAA:A/ ;
+
+// production with tokens, nonterminal-tokens, multi-line
+E ::= <T1> <T2:String> <T3:boolean> <T4:int> <T5:float> <T6:double> <T7:long>
+      /<NT2:String>/ /<NT3:boolean>/ /<NT4:int>/ /<NT5:float>/ /<NT6:double>/ /<NT7:long>/ ;
+
+rel E.NT1 -> A ;
+// inheritance and empty
+F : A ;
+
+// inheritance and more on RHS
+G : C ::= [D] ;
+
+// line comment with special symbols like |, *, ->, <-, <->, [A], B ::= C, :, \n, \r, ~, #, /A/
+/* block comment with special symbols like |, *, ->, <-, <->, [A], B ::= C, :, \n, \r, ~, #, /A/ */
diff --git a/src/test/java/org/jastadd/relast/tests/ConstructorsTest.java b/src/test/java/org/jastadd/relast/tests/ConstructorsTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..689e991ea44e38f6cd96c6211a797b34c9041905
--- /dev/null
+++ b/src/test/java/org/jastadd/relast/tests/ConstructorsTest.java
@@ -0,0 +1,58 @@
+package org.jastadd.relast.tests;
+
+import constructors.ast.*;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+
+/**
+ * Testing generated constructors.
+ *
+ * @author rschoene - Initial contribution
+ */
+@SuppressWarnings("unused")
+public class ConstructorsTest {
+
+  @Test
+  public void testX() {
+    X x = new X();
+    Assertions.assertEquals(1, numberOfConstructors(X.class));
+  }
+
+  @Test
+  public void testY() {
+    Y y0 = new Y();
+    Y y1 = new Y(new S());
+    Assertions.assertEquals(2, numberOfConstructors(Y.class));
+  }
+
+  @Test
+  public void testA() {
+    A a0 = new A();
+    A a1 = new A(new X());
+    Assertions.assertEquals(2, numberOfConstructors(A.class));
+  }
+
+  @Test
+  public void testS() {
+    A a = new A();
+    S s0 = new S();
+    S s1 = new S(a, new List<>(), new Opt<>());
+    S s2 = new S(a, new List<>(), new Opt<>(), new ArrayList<>());
+    Assertions.assertEquals(3, numberOfConstructors(S.class));
+  }
+
+  @Test
+  public void testB() {
+    A a = new A();
+    B b0 = new B();
+    B b1 = new B(a, new List<>(), new Opt<>(), a, new List<>(), new Opt<>());
+    B b2 = new B(a, new List<>(), new Opt<>(), new ArrayList<>(), a, new List<>(), new Opt<>(), null);
+    Assertions.assertEquals(3, numberOfConstructors(B.class));
+  }
+
+  private int numberOfConstructors(Class<?> clazz) {
+    return clazz.getConstructors().length;
+  }
+}
diff --git a/src/test/java/org/jastadd/relast/tests/Errors.java b/src/test/java/org/jastadd/relast/tests/Errors.java
index 718c049708281b26dea16e8792062be067c2938e..5134381a825854479ba6c7b5b179c4310e3a491b 100644
--- a/src/test/java/org/jastadd/relast/tests/Errors.java
+++ b/src/test/java/org/jastadd/relast/tests/Errors.java
@@ -10,6 +10,7 @@ import java.io.File;
 import java.io.IOException;
 import java.nio.charset.Charset;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -23,32 +24,32 @@ class Errors {
   private static final String FILENAME_PATTERN = "$FILENAME";
 
   @Test
-  void test1() throws IOException {
+  void testStandardErrors() throws IOException {
     test("Errors");
   }
 
   @Test
-  void test1Left() throws IOException {
+  void testStandardErrorsLeft() throws IOException {
     test("ErrorsLeft");
   }
 
   @Test
-  void test2() throws IOException {
+  void testInheritance() throws IOException {
     test("Inheritance");
   }
 
   @Test
-  void test2Left() throws IOException {
+  void testInheritanceLeft() throws IOException {
     test("InheritanceLeft");
   }
 
   @Test
-  void test3() throws IOException {
+  void testMultipleFiles() throws IOException {
     test("Multiple", "Multiple_1", "Multiple_2");
   }
 
   @Test
-  void test3Left() throws IOException {
+  void testMultipleFilesLeft() throws IOException {
     test("MultipleLeft", "MultipleLeft_1", "MultipleLeft_2");
   }
 
@@ -60,7 +61,7 @@ class Errors {
     String expectedFile = "./src/test/jastadd/errors/" + name + ".expected";
 
     try {
-      System.out.println(System.getProperty("user.dir"));
+      logger.debug("user.dir: {}", System.getProperty("user.dir"));
       int returnValue = exec(Compiler.class, inFiles.toArray(new String[0]), new File(outFile));
       Assertions.assertEquals(1, returnValue, "Relast did not return with value 1");
     } catch (IOException | InterruptedException e) {
@@ -76,7 +77,14 @@ class Errors {
         expected = expected.replace(FILENAME_PATTERN + (i + 1), inFiles.get(i));
       }
     }
-    Assertions.assertEquals(expected, out);
+    List<String> outList = Arrays.asList(out.split("\n"));
+    Collections.sort(outList);
+    List<String> expectedList = Arrays.stream(expected.split("\n"))
+        .sorted()
+        .filter(s -> !s.isEmpty() && !s.startsWith("//"))
+        .collect(Collectors.toList());
+
+    Assertions.assertLinesMatch(expectedList, outList);
 
     logger.info("relast for " + name + " returned \n{}", out);
   }