Jelajahi Sumber

new: TestContractRunner: copy constructor
new: TestContractRunner: injection of Runner
new: TestContractRunner: #debug()

fix: TestContractRunner: correct method counter when "debug=false"

Ranides Atterwim 10 tahun lalu
induk
melakukan
ba5d51e2bc

+ 71 - 10
assira.junit/src/main/java/net/ranides/assira/junit/TestContractRunner.java

@@ -17,6 +17,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.SortedSet;
 import java.util.TreeSet;
 import java.util.function.Function;
@@ -34,7 +35,7 @@ import org.junit.Ignore;
  * the first one for {@codee HashMap}.
  * @author Ranides Atterwim <ranides@gmail.com>
  */
-public class TestContractRunner {
+public final class TestContractRunner {
 	
 	private final SortedSet<MethodRunner> methods = new TreeSet<>();
     
@@ -52,10 +53,27 @@ public class TestContractRunner {
         this.output = output;
     }
     
+    public TestContractRunner(TestContractRunner runner) {
+        this(runner.output);
+        try {
+            for(TesterWrapper w : runner.testers) {
+                this.appendCopy(w);
+            }
+            this.ignored.addAll(runner.ignored);
+            this.debug = runner.debug;
+        } catch(ReflectiveOperationException cause) {
+            throw NewAssert.rethrow(cause);
+        }
+    }
+    
 	public TestContractRunner debug(boolean value) {
         this.debug = value;
 		return this;
 	}
+    
+    public boolean debug() {
+        return this.debug;
+	}
 	
     public TestContractRunner ignore(String method) {
         this.ignored.add(Pattern.compile(Pattern.quote(method)));
@@ -66,9 +84,25 @@ public class TestContractRunner {
         this.ignored.add(method);
         return this;
     }
+    
+    public TestContractRunner append(Object tester) {
+        appendWrapper(tester);
+        return this;
+    }
+    
+    private void appendCopy(TesterWrapper source) throws ReflectiveOperationException {
+        Object tester = source.object.getClass().newInstance();
+        TesterWrapper target = appendWrapper(tester);
+        for(Entry<String, IParam> entry : source.resources.entrySet()) {
+            String key = entry.getKey();
+            target.resources.get(key).set(entry.getValue().get());
+        }
+    }
+    
 	
-	public TestContractRunner append(Object tester) {
-        testers.add(new TesterWrapper(tester));
+	public TesterWrapper appendWrapper(Object tester) {
+        TesterWrapper wrapper = new TesterWrapper(tester);
+        testers.add(wrapper);
         for(Method m : tester.getClass().getMethods()) {
             if(Modifier.isStatic(m.getModifiers()) ) {
                 continue;
@@ -90,7 +124,7 @@ public class TestContractRunner {
                 methods.add(mr);
             }
         }
-		return this;
+		return wrapper;
 	}
     
     public TestContractRunner param(String name, Object value) {
@@ -109,6 +143,9 @@ public class TestContractRunner {
     }
     
     private boolean irun(TGenerator generator) { //NOPMD
+        for(TesterWrapper tester : testers) {
+            tester.bind(this);
+        }
         Class<?> type = generator.get().getClass();
         Counter counter = new Counter();
         List<String> failed = new ArrayList<>();
@@ -169,7 +206,7 @@ public class TestContractRunner {
         public SMethodRunner(Object that, Method method) {
             super(that, method);
         }
-
+        
         @Override
         protected void invoke(TGenerator argument) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
             method.invoke(that, argument);
@@ -198,7 +235,7 @@ public class TestContractRunner {
             this.uid = type.getName()+"#"+method.getDeclaringClass().getName() +"#" + method.getName();
             this.nid = method.getDeclaringClass().getSimpleName() + "." + method.getName();
         }
-
+        
         @Override
         public int compareTo(MethodRunner object) {
             return uid.compareTo(object.uid);
@@ -219,15 +256,16 @@ public class TestContractRunner {
 					return;
 				}
 			}
+            int index = counter.next();
             try {
                 invoke(param);
 				if(debug) {
-					printf(type, counter.next(), method, "");
+					printf(type, index, method, "");
 				}
             } catch (IllegalAccessException | IllegalArgumentException ex) {
                 throw NewAssert.rethrow(ex);
             } catch (InvocationTargetException ex) {
-				printf(type, counter.next(), method, "FAILED");
+				printf(type, index, method, "FAILED");
 				throw NewAssert.rethrow(ex.getTargetException());
             }
         }
@@ -308,9 +346,14 @@ public class TestContractRunner {
     
     private static final class TesterWrapper {
         
+        private final Object object;
+        
         private final Map<String, IParam> resources = new HashMap<>();
-
+        
+        private final List<IParam> bindings = new ArrayList<>();
+        
         public TesterWrapper(Object object) {
+            this.object = object;
             for(Class<?> c=object.getClass(); c!=null; c=c.getSuperclass()) {
                 for(Field f : c.getDeclaredFields()) {
                     Resource info = f.getAnnotation(Resource.class);
@@ -320,11 +363,21 @@ public class TestContractRunner {
                             name = f.getName();
                         }
                         f.setAccessible(true);
-                        resources.put(name, new IParam(object, f));
+                        if( f.getType().equals(TestContractRunner.class) ) {
+                            bindings.add(new IParam(object, f));
+                        } else {
+                            resources.put(name, new IParam(object, f));
+                        }
                     }
                 }
             }
         }
+                
+        public void bind(TestContractRunner runner) {
+            for(IParam p : bindings) {
+                p.set(runner);
+            }
+        }
         
         public void param(String name, Object value) {
             if( resources.containsKey(name) ) {
@@ -405,6 +458,14 @@ public class TestContractRunner {
             }
         }
         
+        public Object get() {
+            try {
+                return field.get(object);
+            } catch(ReflectiveOperationException cause) {
+                throw NewAssert.rethrow(cause);
+            }
+        }
+        
         public void reset() {
             try {
                 field.set(object, value);

+ 11 - 3
assira.junit/src/test/java/net/ranides/assira/junit/TestContractRunnerTest.java

@@ -12,7 +12,6 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintStream;
 import java.io.UnsupportedEncodingException;
-import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -66,8 +65,11 @@ public class TestContractRunnerTest {
     
     private static final List<String> EXPECTED_RES = Arrays.asList(
         "n=ranides c=33", 
+        "v=text:33", 
         "n=null c=34", 
-        "n=ot c=0"
+        "v=text:34", 
+        "n=ot c=0",
+        "v=text:0" 
     );
 
     private static final List<String> EXPECTED_FUNCTION = Arrays.asList(
@@ -155,8 +157,10 @@ public class TestContractRunnerTest {
     @Test
     public void testResources() {
         TesterObjects.OUT.clear();
+
         TestContractRunner suite = new TestContractRunner(System.err)
-            .append(new Testers.ForResource());
+            .append(new Testers.ForResource1())
+            .append(new Testers.ForResource2());
         suite
             .param("name", "ranides")
             .param("count!", 33)
@@ -167,7 +171,11 @@ public class TestContractRunnerTest {
         suite
             .param("name", "ot")
             .run(() -> new Object());
+        
         assertEquals(EXPECTED_RES, TesterObjects.OUT);
+        
+//        System.out.printf("from = %s%n");
+//        assertEquals("Hello world", tester.out());
     }
     
     private static class TeeStream extends FilterOutputStream {

+ 18 - 1
assira.junit/src/test/java/net/ranides/assira/junit/mockup/Testers.java

@@ -12,6 +12,7 @@ import java.util.function.Function;
 import java.util.function.Supplier;
 import javax.annotation.Resource;
 import net.ranides.assira.junit.TestContract;
+import net.ranides.assira.junit.TestContractRunner;
 import net.ranides.assira.junit.mockup.TesterObjects.*;
 import net.ranides.assira.junit.mockup.TesterInterfaces.*;
 import org.junit.Ignore;
@@ -174,7 +175,10 @@ public class Testers {
         
     }
     
-    public static class ForResource {
+    public static class ForResource1 {
+        
+        @Resource
+        private TestContractRunner runner;
         
         @Resource
         private String name;
@@ -185,8 +189,21 @@ public class Testers {
         @TestContract
         public void run(Object input) {
             TesterObjects.OUT.add("n=" +name + " c="+count);
+            runner.param("out", "text:" + count);
         }
         
     }
     
+    public static class ForResource2 {
+        
+        @Resource
+        private String out;
+        
+        @TestContract
+        public void run(Object input) {
+            TesterObjects.OUT.add("v=" + out);
+        }
+
+    }
+    
 }

+ 1 - 1
assira/src/test/java/net/ranides/assira/collection/suite/lists/ListTester.java

@@ -432,7 +432,7 @@ public class ListTester<T> {
     
     @TestContract
     public void nestedSublistTest(Function<int[], List<T>> f) {
-        TestContractRunner.copy(runner)
+        new TestContractRunner(runner)
             .ignore("ListTester.nestedSublistTest")
             .run(array -> f.apply(array).subList(0, array.length));
     }