From 1acc5ad51b37ed914d527d67da5262fb7b162679 Mon Sep 17 00:00:00 2001 From: heck Date: Tue, 28 Jul 2020 01:45:44 +0200 Subject: [PATCH] PityTest: Duration measurement for TestUnits --- .../foundation/pEp/pitytest/Makefile.conf | 3 +- .../foundation/pEp/pitytest/StopWatch.java | 20 +++ .../foundation/pEp/pitytest/TestResult.java | 8 - .../foundation/pEp/pitytest/TestState.java | 2 +- .../foundation/pEp/pitytest/TestSuite.java | 6 +- .../foundation/pEp/pitytest/TestUnit.java | 168 ++++++++++-------- .../pEp/pitytest/utils/TestUtils.java | 2 +- 7 files changed, 120 insertions(+), 89 deletions(-) create mode 100644 test/java/foundation/pEp/pitytest/StopWatch.java delete mode 100644 test/java/foundation/pEp/pitytest/TestResult.java diff --git a/test/java/foundation/pEp/pitytest/Makefile.conf b/test/java/foundation/pEp/pitytest/Makefile.conf index 9805a1c..fa9b149 100644 --- a/test/java/foundation/pEp/pitytest/Makefile.conf +++ b/test/java/foundation/pEp/pitytest/Makefile.conf @@ -13,5 +13,6 @@ JAVA_CLASSES_PITYTEST= \ utils/TestUtils.class \ utils/Pair.class \ TestState.class \ - TestResult.class + TestResult.class \ + StopWatch.class diff --git a/test/java/foundation/pEp/pitytest/StopWatch.java b/test/java/foundation/pEp/pitytest/StopWatch.java new file mode 100644 index 0000000..7dd77f4 --- /dev/null +++ b/test/java/foundation/pEp/pitytest/StopWatch.java @@ -0,0 +1,20 @@ +package foundation.pEp.pitytest; + +import java.time.Duration; + +public class StopWatch { + private long timeStart = 0; + private long timeEnd = 0; + private Duration duration = null; + + public StopWatch(Runnable lambda) { + timeStart = System.nanoTime(); + lambda.run(); + timeEnd = System.nanoTime(); + duration = Duration.ofNanos(timeEnd - timeStart); + } + + public Duration getDuration() { + return duration; + } +} diff --git a/test/java/foundation/pEp/pitytest/TestResult.java b/test/java/foundation/pEp/pitytest/TestResult.java deleted file mode 100644 index 68e4e46..0000000 --- a/test/java/foundation/pEp/pitytest/TestResult.java +++ /dev/null @@ -1,8 +0,0 @@ -package foundation.pEp.pitytest; - -public enum TestResult { - UNEVALUATED, - SKIPPED, - SUCCESS, - FAILED; -} \ No newline at end of file diff --git a/test/java/foundation/pEp/pitytest/TestState.java b/test/java/foundation/pEp/pitytest/TestState.java index 3f5eb4c..53ee416 100644 --- a/test/java/foundation/pEp/pitytest/TestState.java +++ b/test/java/foundation/pEp/pitytest/TestState.java @@ -7,6 +7,6 @@ public enum TestState { FAILED, STARTING, CTX_INIT, - CTX_INIT_FAILED, + CTX_FAIL, RUNNING; } \ No newline at end of file diff --git a/test/java/foundation/pEp/pitytest/TestSuite.java b/test/java/foundation/pEp/pitytest/TestSuite.java index 2bbe926..f44d355 100644 --- a/test/java/foundation/pEp/pitytest/TestSuite.java +++ b/test/java/foundation/pEp/pitytest/TestSuite.java @@ -98,9 +98,9 @@ public class TestSuite { int failedCount = 0; int successCount = 0; for (TestUnit t : tests) { - if (t.getResult() == TestResult.SKIPPED) skippedCount++; - if (t.getResult() == TestResult.FAILED) failedCount++; - if (t.getResult() == TestResult.SUCCESS) successCount++; + if (t.getResult() == TestState.SKIPPED) skippedCount++; + if (t.getResult() == TestState.FAILED) failedCount++; + if (t.getResult() == TestState.SUCCESS) successCount++; } failedCount = failedCount + skippedCount; diff --git a/test/java/foundation/pEp/pitytest/TestUnit.java b/test/java/foundation/pEp/pitytest/TestUnit.java index 6e543ef..294f1dc 100644 --- a/test/java/foundation/pEp/pitytest/TestUnit.java +++ b/test/java/foundation/pEp/pitytest/TestUnit.java @@ -3,30 +3,38 @@ package foundation.pEp.pitytest; import foundation.pEp.pitytest.utils.TestUtils; import static foundation.pEp.pitytest.TestLogger.*; -import static foundation.pEp.pitytest.utils.TestUtils.TermColor; -import static foundation.pEp.pitytest.utils.TestUtils.colorString; +import static foundation.pEp.pitytest.utils.TestUtils.*; +import java.text.DecimalFormat; +import java.time.Duration; import java.util.function.Consumer; -//Automatically get added to the default TestSuite always -//Can be added to any nr of TestSuites +// Automatically gets added to the default TestSuite always +// Can be added to any nr of TestSuites public class TestUnit implements Runnable { private String testUnitName = "default test unit"; private T ctx; private Consumer lambda; - private TestResult result = TestResult.UNEVALUATED; + private TestState result = TestState.UNEVALUATED; private TestState state = TestState.UNEVALUATED; private Throwable lastException; + private Duration testDuration = null; private boolean verboseMode = true; private TermColor testColor = TermColor.CYAN; // Defaults (line width 80) - private int logFmtTestNameLen = 35; - private int logFmtCtxNameLen = 25; + // fixed width + private int logFmtPadding = 4; private int logFmtMsgLen = 12; + private int logFmtTestDuration = 14; + private int lineWidthMin = logFmtPadding + logFmtMsgLen + logFmtTestDuration + 20; + + // dynamic + private int logFmtTestNameLen = 32; + private int logFmtCtxNameLen = 20; public TestUnit(String name, T context, Consumer lambda) { this.testUnitName = name; @@ -52,7 +60,7 @@ public class TestUnit implements Runnable { this.testColor = testColor; } - public TestResult getResult() { + public TestState getResult() { return result; } @@ -73,93 +81,80 @@ public class TestUnit implements Runnable { public void run() { TestUtils.standardOutErrEnabled(verboseMode); if (ctx.isUninitializable()) { - setTestState(TestState.CTX_INIT_FAILED); + setTestState(TestState.CTX_FAIL); TestUtils.standardOutErrEnabled(true); - return; - } - try { - setTestState(TestState.STARTING); - // Init the Context if not already done - if (!ctx.isInitialized()) { - //Context init problems need to throw to fail - try { - setTestState(TestState.CTX_INIT); - setTermColor(testColor); - ctx.init(); - setTermColor(TermColor.RESET); - } catch (Throwable t) { - lastException = t; - setTermColor(TermColor.RESET); - setTestState(TestState.CTX_INIT_FAILED); - TestUtils.standardOutErrEnabled(true); - return; + } else { + try { + setTestState(TestState.STARTING); + // Init the Context if not already done + if (!ctx.isInitialized()) { + //Context init problems need to throw to fail + try { + setTestState(TestState.CTX_INIT); + setTermColor(testColor); + ctx.init(); + setTermColor(TermColor.RESET); + } catch (Throwable t) { + lastException = t; + setTermColor(TermColor.RESET); + ctx.setUninitializable(true); + setTestState(TestState.CTX_FAIL); + TestUtils.standardOutErrEnabled(true); + return; + } + ctx.setInitialized(true); } - ctx.setInitialized(true); + //tests need to throw to fail + setTestState(TestState.RUNNING); + setTermColor(testColor); + testDuration = new StopWatch(() -> { + lambda.accept(ctx); + }).getDuration(); + setTermColor(TermColor.RESET); + setTestState(TestState.SUCCESS); + } catch (Throwable t) { + lastException = t; + setTermColor(TermColor.RESET); + setTestState(TestState.FAILED); + TestUtils.standardOutErrEnabled(true); + return; } - //tests need to throw to fail - setTestState(TestState.RUNNING); - setTermColor(testColor); - lambda.accept(ctx); - setTermColor(TermColor.RESET); - setTestState(TestState.SUCCESS); - } catch (Throwable t) { - lastException = t; setTermColor(TermColor.RESET); - setTestState(TestState.FAILED); TestUtils.standardOutErrEnabled(true); - return; } - setTermColor(TermColor.RESET); - TestUtils.standardOutErrEnabled(true); } private void setTestState(TestState s) { state = s; switch (state) { - case UNEVALUATED: { - setTestResult(TestResult.UNEVALUATED); - break; - } - case SKIPPED: { - setTestResult(TestResult.SKIPPED); - break; - } - case SUCCESS: { - setTestResult(TestResult.SUCCESS); - break; - } + case UNEVALUATED: + case SKIPPED: + case SUCCESS: case FAILED: { - setTestResult(TestResult.FAILED); + setTestResult(s); break; } - case STARTING: case CTX_INIT: + case STARTING: case RUNNING: { - logH1(makeLogString(state.toString())); + logH1(makeLogString()); break; } - case CTX_INIT_FAILED: { - logH1(makeLogString(state.toString())); - setTestResult(TestResult.SKIPPED); + case CTX_FAIL: { + setTestResult(TestState.SKIPPED); +// logH1(makeLogString()); break; } } } - private void setTestResult(TestResult r) { + private void setTestResult(TestState r) { + assert (r == TestState.SKIPPED || r == TestState.FAILED || r == TestState.SUCCESS || r == TestState.UNEVALUATED ): "PityTest Internal: illegal result value '" + r +"'"; result = r; - String resultStr = r.toString(); - - if(r != TestResult.SUCCESS) { - resultStr = colorString(resultStr, TermColor.RED); - } else { - resultStr = colorString(resultStr, TermColor.GREEN); - } - TestUtils.standardOutErrEnabled(true); - logH1(makeLogString(resultStr)); - if( r != TestResult.SUCCESS) { + logH1(makeLogString()); + if (result == TestState.FAILED || result == TestState.CTX_FAIL) { log("ERROR: " + getLastException().toString()); } if (verboseMode) logRaw("\n\n"); @@ -167,16 +162,39 @@ public class TestUnit implements Runnable { } private void logLayout() { - logFmtTestNameLen = (int) Math.floor(TestLogger.getMsgWidth() * 0.39); - logFmtCtxNameLen = (int) Math.floor(TestLogger.getMsgWidth() * 0.28); - logFmtMsgLen = (int) Math.floor(TestLogger.getMsgWidth() * 0.25); + int lineWidth = TestLogger.getMsgWidth(); + // Fixed sizes + lineWidth -= logFmtPadding; + lineWidth -= logFmtMsgLen; + lineWidth -= logFmtTestDuration; + lineWidth = clip(lineWidth, lineWidthMin, Integer.MAX_VALUE); + + // Proportional (dynamic sizes) + logFmtTestNameLen = (int) Math.floor(lineWidth * 0.45); + logFmtCtxNameLen = (int) Math.floor(lineWidth * 0.45); } - private String makeLogString(String str) { + private String makeLogString() { + String resultStr = state.toString(); + if (state == TestState.FAILED) { + resultStr = colorString(resultStr, TermColor.RED); + } else if (state == TestState.SUCCESS) { + resultStr = colorString(resultStr, TermColor.GREEN); + } + String testUnitNameFmtd = TestUtils.padOrClipString(" TEST: '" + testUnitName + "' ", "=", logFmtTestNameLen, TestUtils.Alignment.Left, ".. "); String testCtxNameFmtd = TestUtils.padOrClipString(" CTX: '" + ctx.getTestContextName() + "' ", "=", logFmtCtxNameLen, TestUtils.Alignment.Center, ".. "); - String strFmtd = TestUtils.padOrClipString(" " + str + " ", "=", logFmtMsgLen, TestUtils.Alignment.Right, ".. "); - return testUnitNameFmtd + testCtxNameFmtd + strFmtd; + String strTestDuration = ""; + if (state == TestState.SUCCESS) { + DecimalFormat f = new DecimalFormat("0.000"); + String durationFmtd = f.format(testDuration.toMillis() / 1000.0); + strTestDuration = TestUtils.padOrClipString(" [" + durationFmtd + " sec] ", "=", logFmtTestDuration, TestUtils.Alignment.Right, ".. "); + } else { + strTestDuration = TestUtils.padOrClipString("", "=", logFmtTestDuration, TestUtils.Alignment.Right, ".. "); + } + + String strFmtd = TestUtils.padOrClipString(" " + resultStr + " ", "=", logFmtMsgLen, TestUtils.Alignment.Right, ".. "); + return testUnitNameFmtd + testCtxNameFmtd + strTestDuration + strFmtd; } } diff --git a/test/java/foundation/pEp/pitytest/utils/TestUtils.java b/test/java/foundation/pEp/pitytest/utils/TestUtils.java index f6df12c..f18d6b4 100644 --- a/test/java/foundation/pEp/pitytest/utils/TestUtils.java +++ b/test/java/foundation/pEp/pitytest/utils/TestUtils.java @@ -140,7 +140,7 @@ public class TestUtils { public static String padOrClipString(String str, String padChar, int len, Alignment alignment, String clipMsg) { String ret = ""; int strLen = str.length(); - len += (substringOccurencesCount(str, "\u001B") * 4); + len += (substringOccurencesCount(str, "\u001B") * 4.5); if (strLen <= len) { if (alignment == Alignment.Left) { ret = str + repeatString(padChar, len - strLen);