minor refactoring of the test executor

This commit is contained in:
hneemann 2020-11-07 15:28:58 +01:00
parent 1de3a42570
commit b04b469b71
8 changed files with 108 additions and 113 deletions

View File

@ -74,20 +74,20 @@ public class CommandLineTester {
try { try {
ErrorDetector errorDetector = new ErrorDetector(); ErrorDetector errorDetector = new ErrorDetector();
TestExecutor te = new TestExecutor(t, circuitLoader.getCircuit(), circuitLoader.getLibrary()) TestExecutor.Result tr = new TestExecutor(t, circuitLoader.getCircuit(), circuitLoader.getLibrary())
.setAllowMissingInputs(allowMissingInputs) .setAllowMissingInputs(allowMissingInputs)
.addObserver(errorDetector) .addObserver(errorDetector)
.create(); .execute();
if (te.allPassed()) { if (tr.allPassed()) {
out.println(label + ": passed"); out.println(label + ": passed");
testsPassed++; testsPassed++;
} else { } else {
String message = label + ": failed"; String message = label + ": failed";
if (te.isErrorOccurred()) if (tr.isErrorOccurred())
message += " due to an error"; message += " due to an error";
else else
message += " (" + te.failedPercent() + "%)"; message += " (" + tr.failedPercent() + "%)";
out.println(message); out.println(message);
errorCount++; errorCount++;
} }

View File

@ -365,17 +365,6 @@ public class Circuit implements Copyable<Circuit> {
private final boolean hasGenericCode; private final boolean hasGenericCode;
private final VisualElement visualElement; private final VisualElement visualElement;
/**
* Used in some test cases.
* Don't use this constructor in production code!
*
* @param testCaseDescription the test case description
*/
public TestCase(TestCaseDescription testCaseDescription) {
this(new VisualElement(TestCaseElement.DESCRIPTION.getName())
.setAttribute(Keys.TESTDATA, testCaseDescription));
}
private TestCase(VisualElement visualElement) { private TestCase(VisualElement visualElement) {
this.visualElement = visualElement; this.visualElement = visualElement;
ElementAttributes attr = visualElement.getElementAttributes(); ElementAttributes attr = visualElement.getElementAttributes();
@ -406,7 +395,7 @@ public class Circuit implements Copyable<Circuit> {
} }
/** /**
* @return the visual element which contains the test case, maybe null * @return the visual element which contains the test case
*/ */
public VisualElement getVisualElement() { public VisualElement getVisualElement() {
return visualElement; return visualElement;
@ -425,7 +414,6 @@ public class Circuit implements Copyable<Circuit> {
TestCase testCase = (TestCase) o; TestCase testCase = (TestCase) o;
return label.equals(testCase.label); return label.equals(testCase.label);
} }
@Override @Override

View File

@ -125,13 +125,13 @@ public class ValueTableDialog extends JDialog {
for (Circuit.TestCase ts : tsl) { for (Circuit.TestCase ts : tsl) {
ErrorDetector errorDetector = new ErrorDetector(); ErrorDetector errorDetector = new ErrorDetector();
try { try {
TestExecutor testExecutor = new TestExecutor(ts, circuit, library) TestExecutor.Result testResult = new TestExecutor(ts, circuit, library)
.addObserver(errorDetector) .addObserver(errorDetector)
.create(); .execute();
String tabName; String tabName;
Icon tabIcon; Icon tabIcon;
if (testExecutor.allPassed()) { if (testResult.allPassed()) {
tabName = Lang.get("msg_test_N_Passed", ts.getLabel()); tabName = Lang.get("msg_test_N_Passed", ts.getLabel());
tabIcon = ICON_PASSED; tabIcon = ICON_PASSED;
} else { } else {
@ -139,13 +139,13 @@ public class ValueTableDialog extends JDialog {
tabIcon = ICON_FAILED; tabIcon = ICON_FAILED;
errorTabIndex = i; errorTabIndex = i;
} }
if (testExecutor.toManyResults()) if (testResult.toManyResults())
tabName += " " + Lang.get("msg_test_missingLines"); tabName += " " + Lang.get("msg_test_missingLines");
tp.addTab(tabName, tabIcon, new JScrollPane(createTable(testExecutor.getResult()))); tp.addTab(tabName, tabIcon, new JScrollPane(createTable(testResult.getValueTable())));
if (testExecutor.toManyResults()) if (testResult.toManyResults())
tp.setToolTipTextAt(i, new LineBreaker().toHTML().breakLines(Lang.get("msg_test_missingLines_tt"))); tp.setToolTipTextAt(i, new LineBreaker().toHTML().breakLines(Lang.get("msg_test_missingLines_tt")));
resultTableData.add(testExecutor.getResult()); resultTableData.add(testResult.getValueTable());
i++; i++;
errorDetector.check(); errorDetector.check();
} catch (Exception e) { } catch (Exception e) {

View File

@ -199,9 +199,9 @@ public class FolderTestRunner {
int rowCount = 0; int rowCount = 0;
for (Circuit.TestCase tc : testCases) { for (Circuit.TestCase tc : testCases) {
try { try {
TestExecutor te = new TestExecutor(tc, circuit, library).create(); TestExecutor.Result tr = new TestExecutor(tc, circuit, library).execute();
if (te.allPassed()) { if (tr.allPassed()) {
rowCount += te.getResult().getRows(); rowCount += tr.getValueTable().getRows();
} else { } else {
if (sb.length() > 0) if (sb.length() > 0)
sb.append("; "); sb.append("; ");

View File

@ -57,7 +57,7 @@ public class TestExecutor {
* @throws NodeException NodeException * @throws NodeException NodeException
*/ */
public TestExecutor(Circuit.TestCase testCase, Circuit circuit, ElementLibrary library) throws TestingDataException, NodeException, ElementNotFoundException, PinException { public TestExecutor(Circuit.TestCase testCase, Circuit circuit, ElementLibrary library) throws TestingDataException, NodeException, ElementNotFoundException, PinException {
this(testCase, createModel(testCase, circuit, library)); this(testCase.getTestCaseDescription(), createModel(testCase, circuit, library));
} }
static private Model createModel(Circuit.TestCase testCase, Circuit circuit, ElementLibrary library) throws NodeException, ElementNotFoundException, PinException { static private Model createModel(Circuit.TestCase testCase, Circuit circuit, ElementLibrary library) throws NodeException, ElementNotFoundException, PinException {
@ -71,30 +71,30 @@ public class TestExecutor {
} }
/** /**
* Use for tests only! Do'nt use this constructor with a model you have created from a circuit. * Use for tests only! Don't use this constructor with a model you have created from a circuit.
* If a circuit is available use the other constructor. * If a circuit is available use the constructor above.
* *
* @param testCase the test case * @param testCase the test case
* @param model the model * @param model the model
* @throws TestingDataException TestingDataException * @throws TestingDataException TestingDataException
*/ */
public TestExecutor(Circuit.TestCase testCase, Model model) throws TestingDataException { public TestExecutor(TestCaseDescription testCase, Model model) throws TestingDataException {
names = testCase.getTestCaseDescription().getNames(); names = testCase.getNames();
this.model = model; this.model = model;
results = new ValueTable(names); results = new ValueTable(names);
visibleRows = 0; visibleRows = 0;
lines = testCase.getTestCaseDescription().getLines(); lines = testCase.getLines();
} }
/** /**
* Creates the result by comparing the testing vector with the given model- * Creates the result by comparing the testing vector with the given model
* *
* @return this for chained calls * @return the result of the test execution
* @throws TestingDataException DataException * @throws TestingDataException DataException
* @throws NodeException NodeException * @throws NodeException NodeException
* @throws ParserException ParserException * @throws ParserException ParserException
*/ */
public TestExecutor create() throws TestingDataException, NodeException, ParserException { public TestExecutor.Result execute() throws TestingDataException, NodeException, ParserException {
try { try {
HashSet<String> usedSignals = new HashSet<>(); HashSet<String> usedSignals = new HashSet<>();
inputs = new ArrayList<>(); inputs = new ArrayList<>();
@ -153,7 +153,7 @@ public class TestExecutor {
lines.emitLines(new LineListenerResolveDontCare(values -> checkRow(model, values), inputs), new Context().setModel(model)); lines.emitLines(new LineListenerResolveDontCare(values -> checkRow(model, values), inputs), new Context().setModel(model));
return this; return new Result();
} finally { } finally {
model.close(); model.close();
} }
@ -243,6 +243,68 @@ public class TestExecutor {
toManyResults = true; toManyResults = true;
} }
private int getIndexOf(String name) {
if (name == null || name.length() == 0)
return -1;
for (int i = 0; i < names.size(); i++) {
String n = names.get(i);
if (n.equals(name))
return i;
}
return -1;
}
/**
* Allow missing inputs
*
* @param allowMissingInputs if true, missing inputs are allowed
* @return this for chained calls
*/
public TestExecutor setAllowMissingInputs(boolean allowMissingInputs) {
this.allowMissingInputs = allowMissingInputs;
return this;
}
/**
* Adds a observer to the model of this test executor
*
* @param observer the observer to add
* @return this for chained calls
*/
public TestExecutor addObserver(ModelStateObserverTyped observer) {
model.addObserver(observer);
return this;
}
/**
* A test signal
*/
public final static class TestSignal {
private final int index;
private final ObservableValue value;
private TestSignal(int index, ObservableValue value) {
this.index = index;
this.value = value;
}
/**
* @return the index of this value
*/
public int getIndex() {
return index;
}
}
/**
* The result of the test execution
*/
public final class Result {
private Result() {
}
/** /**
* @return true if all tests have passed * @return true if all tests have passed
*/ */
@ -279,65 +341,11 @@ public class TestExecutor {
return toManyResults; return toManyResults;
} }
private int getIndexOf(String name) {
if (name == null || name.length() == 0)
return -1;
for (int i = 0; i < names.size(); i++) {
String n = names.get(i);
if (n.equals(name))
return i;
}
return -1;
}
/** /**
* @return return the result * @return the value table containing the detailed result
*/ */
public ValueTable getResult() { public ValueTable getValueTable() {
return results; return results;
} }
/**
* Allow missing inputs
*
* @param allowMissingInputs if true, missing inputs are allowed
* @return this for chained calls
*/
public TestExecutor setAllowMissingInputs(boolean allowMissingInputs) {
this.allowMissingInputs = allowMissingInputs;
return this;
}
/**
* Adds a observer to the model of this test executor
*
* @param observer the observer to add
* @return this for chained calls
*/
public TestExecutor addObserver(ModelStateObserverTyped observer) {
model.addObserver(observer);
return this;
}
/**
* A test signal
*/
public static class TestSignal {
private final int index;
private final ObservableValue value;
TestSignal(int index, ObservableValue value) {
this.index = index;
this.value = value;
}
/**
* @return the index of this value
*/
public int getIndex() {
return index;
} }
} }
}

View File

@ -34,6 +34,6 @@ public class JarComponentManagerTest extends TestCase {
}; };
for (Circuit.TestCase tc : br.getCircuit().getTestCases()) for (Circuit.TestCase tc : br.getCircuit().getTestCases())
assertTrue(new TestExecutor(tc, br.getCircuit(), br.getLibrary()).create().allPassed()); assertTrue(new TestExecutor(tc, br.getCircuit(), br.getLibrary()).execute().allPassed());
} }
} }

View File

@ -6,7 +6,6 @@
package de.neemann.digital.integration; package de.neemann.digital.integration;
import de.neemann.digital.core.ErrorDetector; import de.neemann.digital.core.ErrorDetector;
import de.neemann.digital.core.Model;
import de.neemann.digital.core.NodeException; import de.neemann.digital.core.NodeException;
import de.neemann.digital.core.element.Keys; import de.neemann.digital.core.element.Keys;
import de.neemann.digital.draw.elements.Circuit; import de.neemann.digital.draw.elements.Circuit;
@ -83,9 +82,9 @@ public class TestExamples extends TestCase {
String label = tc.getLabel(); String label = tc.getLabel();
ErrorDetector ed = new ErrorDetector(); ErrorDetector ed = new ErrorDetector();
TestExecutor tr = new TestExecutor(tc, br.getCircuit(), br.getLibrary()) TestExecutor.Result tr = new TestExecutor(tc, br.getCircuit(), br.getLibrary())
.addObserver(ed) .addObserver(ed)
.create(); .execute();
if (label.contains("Failing")) if (label.contains("Failing"))
assertFalse(dig.getName() + ":" + label, tr.allPassed()); assertFalse(dig.getName() + ":" + label, tr.allPassed());

View File

@ -47,8 +47,8 @@ public class TestResultTest extends TestCase {
+ "0 1 1\n" + "0 1 1\n"
+ "1 0 1\n" + "1 0 1\n"
+ "1 1 0\n"); + "1 1 0\n");
TestExecutor tr = new TestExecutor(new Circuit.TestCase(data), model).create(); TestExecutor.Result tr = new TestExecutor(data, model).execute();
assertEquals(4, tr.getResult().getRows()); assertEquals(4, tr.getValueTable().getRows());
assertTrue(tr.allPassed()); assertTrue(tr.allPassed());
} }
@ -60,14 +60,14 @@ public class TestResultTest extends TestCase {
+ "0 1 1\n" + "0 1 1\n"
+ "1 0 1\n" + "1 0 1\n"
+ "1 1 0\n"); + "1 1 0\n");
TestExecutor te = new TestExecutor(new Circuit.TestCase(data), model).create(); TestExecutor.Result tr = new TestExecutor(data, model).execute();
ValueTable tr = te.getResult(); ValueTable valueTable = tr.getValueTable();
assertEquals(4, tr.getRows()); assertEquals(4, valueTable.getRows());
assertFalse(te.allPassed()); assertFalse(tr.allPassed());
assertEquals(true, ((MatchedValue) tr.getValue(0, 2)).isPassed()); assertEquals(true, ((MatchedValue) valueTable.getValue(0, 2)).isPassed());
assertEquals(true, ((MatchedValue) tr.getValue(1, 2)).isPassed()); assertEquals(true, ((MatchedValue) valueTable.getValue(1, 2)).isPassed());
assertEquals(true, ((MatchedValue) tr.getValue(2, 2)).isPassed()); assertEquals(true, ((MatchedValue) valueTable.getValue(2, 2)).isPassed());
assertEquals(false, ((MatchedValue) tr.getValue(3, 2)).isPassed()); assertEquals(false, ((MatchedValue) valueTable.getValue(3, 2)).isPassed());
} }
public void testResultDontCare() throws Exception { public void testResultDontCare() throws Exception {
@ -78,10 +78,10 @@ public class TestResultTest extends TestCase {
+ "0 1 1\n" + "0 1 1\n"
+ "1 0 1\n" + "1 0 1\n"
+ "1 1 x\n"); + "1 1 x\n");
TestExecutor te = new TestExecutor(new Circuit.TestCase(data), model).create(); TestExecutor.Result tr = new TestExecutor(data, model).execute();
ValueTable tr = te.getResult(); ValueTable valueTable = tr.getValueTable();
assertEquals(4, tr.getRows()); assertEquals(4, valueTable.getRows());
assertTrue(te.allPassed()); assertTrue(tr.allPassed());
} }
public void testResultDontCare2() throws Exception { public void testResultDontCare2() throws Exception {
@ -92,10 +92,10 @@ public class TestResultTest extends TestCase {
+ "0 1 1\n" + "0 1 1\n"
+ "1 0 1\n" + "1 0 1\n"
+ "1 1 1\n"); + "1 1 1\n");
TestExecutor te = new TestExecutor(new Circuit.TestCase(data), model).create(); TestExecutor.Result tr = new TestExecutor(data, model).execute();
ValueTable tr = te.getResult(); ValueTable valueTable = tr.getValueTable();
assertEquals(4, tr.getRows()); assertEquals(4, valueTable.getRows());
assertTrue(te.allPassed()); assertTrue(tr.allPassed());
} }
public void testResultDontCareInput() throws Exception { public void testResultDontCareInput() throws Exception {
@ -104,10 +104,10 @@ public class TestResultTest extends TestCase {
"A B Y\n" "A B Y\n"
+ "x 0 0\n" + "x 0 0\n"
+ "x 1 1\n"); + "x 1 1\n");
TestExecutor te = new TestExecutor(new Circuit.TestCase(data), model).create(); TestExecutor.Result tr = new TestExecutor(data, model).execute();
ValueTable tr = te.getResult(); ValueTable valueTable = tr.getValueTable();
assertEquals(4, tr.getRows()); assertEquals(4, valueTable.getRows());
assertTrue(te.allPassed()); assertTrue(tr.allPassed());
} }
public void testResultDontCareInput2() throws Exception { public void testResultDontCareInput2() throws Exception {
@ -116,10 +116,10 @@ public class TestResultTest extends TestCase {
"A B C Y\n" "A B C Y\n"
+ "x x 0 0\n" + "x x 0 0\n"
+ "x x 1 1\n"); + "x x 1 1\n");
TestExecutor te = new TestExecutor(new Circuit.TestCase(data), model).create(); TestExecutor.Result tr = new TestExecutor(data, model).execute();
ValueTable tr = te.getResult(); ValueTable valueTable = tr.getValueTable();
assertEquals(8, tr.getRows()); assertEquals(8, valueTable.getRows());
assertTrue(te.allPassed()); assertTrue(tr.allPassed());
} }
} }