{"id":3009,"date":"2019-10-10T09:13:15","date_gmt":"2019-10-09T21:13:15","guid":{"rendered":"https:\/\/www.deltics.co.nz\/blog\/?p=3009"},"modified":"2019-10-10T09:13:15","modified_gmt":"2019-10-09T21:13:15","slug":"smoketest-2-0-3-update","status":"publish","type":"post","link":"https:\/\/www.deltics.co.nz\/blog\/posts\/3009\/","title":{"rendered":"Smoketest 2.0.3 Update"},"content":{"rendered":"<span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">5<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span>\n<p>Some minor improvements to the <strong>Smoketest<\/strong> framework went live earlier this week.  Some cosmetic, some functional.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h4 class=\"wp-block-heading\">More than Skin Deep<\/h4>\n\n\n\n<p>The most subtle change in this release is in the form of additional documentation added to the comments in the implementation itself.<\/p>\n\n\n\n<p>I hope people find that useful.  \ud83d\ude42<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Just a Prettier Face<\/h4>\n\n\n\n<p>On the cosmetic front, console output from the test run is now improved [<em>subjective opinion only, ymmv &#8211; Ed<\/em>].<\/p>\n\n\n\n<p>The first thing taken care of was the display of tests outcomes with overridden expectations.  This is something that is only relevant to the special case of the self-tests provided with the framework but now means that when a self-test is expected to fail, if it correctly fails then this is now reported as a PASS in the console output.  Correct outcomes were already taken care of in the results writers, so this was just an inconsistency that needed tidying up. <\/p>\n\n\n\n<p>In more general changes, output from tests in different test classes are now separated visually by a single blank line and each test class is introduced.  Test outcomes recorded by the methods in that class are then output with a leading <code>+<\/code> resulting in a pleasing indentation of those test results relative to the containing class.<\/p>\n\n\n\n<p>Any warnings output by the test run are not indented or prefixed helping these to stand out from the test outcomes.<\/p>\n\n\n\n<p>One of the warnings now output is in the case of a test method that performs no tests.  That is, no test results are recorded during the execution of that method.<\/p>\n\n\n\n<p><code>WARNING: Test method &lt;className&gt;.&lt;methodName&gt; did not perform any tests<\/code><\/p>\n\n\n\n<p>A similar warning is emitted if a test class fails to implement <em>any<\/em> test methods at all:<\/p>\n\n\n\n<p><code>WARNING: Test class &lt;className&gt; implements no test methods<\/code><\/p>\n\n\n\n<p>In both cases the warning has no impact on any test results written by any writer and in fact are not even detectable to a results writer.  They are emitted solely by the test runner.<\/p>\n\n\n\n<p>For the first of these methods a mechanism is provided to suppress this warning if required.  Which brings us to the functional changes.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">NOT Just a Prettier Face<\/h4>\n\n\n\n<p>Any method that deliberately and knowingly does not perform any test methods can call <code>TestRun.PerformsNoTests<\/code> to suppress the <code>no test methods<\/code> warning.<\/p>\n\n\n\n<p>Why would you do this ?<\/p>\n\n\n\n<p>I provided this as I ran into a scenario when expanding the self-tests where I wanted to perform some scaffolding of some test data before subsequents test methods were executed.  Rather than overloading a test method with this scaffolding in addition to performing an initial test, I decided that such things should be handled specifically by scaffolding methods.<\/p>\n\n\n\n<p>Such methods still need to be published as test methods for the test runner to be able to discover and execute them.<\/p>\n\n\n\n<p>The specific example, if you are interested, is the <code>CaptureStats<\/code> method of the <code>TCoreFunctionalityTests<\/code> in the <code>tests\\selftest<\/code> project.<\/p>\n\n\n\n<p class=\"has-background has-pale-pink-background-color\">Currently this sort of thing relies on predictable order of execution based on the declared order of methods in the test class declaration.  This makes me nervous and may be revisited to find a more robust solution but does the job that is needed for now.<\/p>\n\n\n\n<p>A bigger, but somewhat related, change is in the fact that <strong>Setup<\/strong> and <strong>Teardown<\/strong> methods are now supported.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<h4 class=\"wp-block-heading\">Set Me Up and Tear Me Down&#8230;<\/h4>\n\n\n\n<p>Setup and Teardown relies on test methods in a class having special names.  Test methods with these names are removed from the list of test methods executed as part of the test class and are instead invoked at specific points during test execution for that class:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Method Name       When The Method Is Called\n---------------   -------------------------------------------------\nSetupTest         ONCE per test class run, before any test methods\n                   in the class\n\nSetupMethod       ONCE PER TEST METHOD, before each and every\n                   test method in the class\n\nTeardownMethod    ONCE PER TEST METHOD, after each and\n                   every test method in the class\n\nTeardownTest      ONCE per test class run, after all test methods\n                   in a class<\/pre>\n\n\n\n<p>These methods do not have to be &#8216;paired up&#8217;.  You can have <strong>Setup<\/strong> methods without corresponding <strong>Teardown<\/strong> methods, and\/or vice-versa.  When any of these methods is present a line is output to the console to indicate their execution.<\/p>\n\n\n\n<p class=\"has-background has-luminous-vivid-amber-background-color\">There is nothing currently to stop you from writing tests in these methods, it&#8217;s just not a good idea to do so.  It would be possible to abend a test run if test results were detected from these methods and this may be added in the future, or at least a WARNING emitted when this occurs. <\/p>\n\n\n\n<p>It also doesn&#8217;t matter where these methods are declared, relative to any other test methods.  They do still need to be <code>published<\/code> methods but can appear anywhere in the list of such methods.  As long as they are named with the correct names as described above, they will be identified and invoked by the test runner at the appropriate points, automatically.<\/p>\n\n\n\n<p class=\"has-background has-pale-pink-background-color\"><strong>NOTE:<\/strong> If an exception escapes from any of these methods it will be caught and logged to the console but the test runner will then carry on with the test run as normal.<\/p>\n\n\n\n<p>For an example of these methods in action you can again consult the self tests, specifically in this case the <code>TCommandLineHandlingTests<\/code> in <code>Test.CommandLineHandling<\/code>.<\/p>\n\n\n\n<p>For some idea of the impact of these changes, here&#8217;s a capture of a test run of those self tests:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-\">Smoketest test run: Name=selftest.exe, Environment=Delphi XE4\nWriters supported: xunit2\n\nExecuting tests in TCoreFunctionalityTests:\n+ This test passed: PASSED\n+ This test failed: PASSED\n+ ThisTestWillThrowAnException test 1: PASSED\n+ ThisTestWillThrowAnException test 1 threw expected exception [Exception: This exception was deliberately raised]\n+ 3 tests recorded to this point: PASSED\n+ 1 test passed at this point: PASSED\n+ 1 test failed at this point: PASSED\n+ 1 test error at this point: PASSED \n\nExecuting tests in TExceptionHandlingTests:\n+ EDivByZero caught by AssertException(EDivByZero): PASSED\n+ EDivByZero caught by AssertBaseException(Exception): PASSED\n+ EDivByZero not caught by Assert(Exception) causes test to fail: PASSED\n+ Unexpected Exception raised causes test to fail: PASSED \n\nExecuting tests in TCommandLineHandlingTests:\nPerforming setup for test\nPerforming setup for method:SwitchPresentWithNoValueIsHandledCorrectly\n+ Present -switch is identified: PASSED\n+ Present -switch has no value: PASSED\nPerforming setup for method:SwitchPresentWithValueIsHandledCorrectly\n+ -mode switch is identified: PASSED\n+ -mode value is &#039;level=42&#039;: PASSED\nPerforming setup for method:SwitchNotPresentIsHandledCorrectly\n+ Missing -lever is not identified: PASSED\n+ Missing -lever has no value: PASSED\nPerforming setup for method:QuotedValueIsUnquotedCorrectly\n+ Quoted value is unquoted correctly: PASSED\n+ Performing teardown for test \n\nTotal Tests = 18, Passed = 18, Failed = 0, Skipped = 0, Errors = 0<\/code><\/pre>\n\n\n\n<p>All of these changes have no impact on the results writers which continue to function as before.<\/p>\n\n\n\n<p>One small change which <em>has<\/em> had a minor impact on results writers is that the <code>Runtime<\/code> property on the test run, which records the elapsed time of the overall test run.  This is now reported in milliseconds rather than seconds.<\/p>\n\n\n\n<p>The existing <strong>xUnit2<\/strong> results writer has already been updated to reflect this and so provide more &#8216;accurate&#8217; timings in the results that it produces.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<h4 class=\"wp-block-heading\">More To Come<\/h4>\n\n\n\n<p>As part of the implementation of <strong>duget<\/strong> I am going through my existing libraries of code that I rely on extensively, re-organising them for packaging with <strong>duget<\/strong>.  Part of this involves migrating the tests to <strong>Smoketest 2.0<\/strong> (or adding them where not already present).<\/p>\n\n\n\n<p>This is driving further improvements to <strong>Smoketest 2.0<\/strong>, with a lot of work at the moment in the Api for expressing <strong>Assert<\/strong>s but it&#8217;s all quite fluid at the moment.<\/p>\n\n\n\n<p>This will be a significant addition to the framework and I anticipate a bump to 2.1.0 once things have settled down and I have a clear direction for the future evolution of this aspect of the framework.<\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">5<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span> An overview of the changes in Smoketest 2.0.3 including Setup\/Teardown methods and improved formatting of console output.<\/p>\n","protected":false},"author":2,"featured_media":2957,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"jetpack_publicize_message":"Overview of the Smoketest 2.0.3 Update - In Summary: Setup\/Teardown methods and improved formatting of console output.","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":[]},"categories":[323,4,321,348,48],"tags":[327,329,51,349,295],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/vape_2.jpg?fit=1229%2C314&ssl=1","jetpack_shortlink":"https:\/\/wp.me\/p1TKYv-Mx","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":2956,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2956\/","url_meta":{"origin":3009,"position":0},"title":"Introducing: Smoketest 2.0","date":"24 Sep 2019","format":false,"excerpt":"Meet the new Smoketest. Nothing like the old Smoketest. A new, ultra-lightweight unit testing framework with xUnit 2.x result output (and the ability to support other output formats as needed).","rel":"","context":"In &quot;automation&quot;","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/vape_2.jpg?fit=1200%2C307&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":2144,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2144\/","url_meta":{"origin":3009,"position":1},"title":"Smoketest 1.0 &#8211; Release and Be Damned!","date":"14 Nov 2013","format":false,"excerpt":"As I have been promising for some time (quite literally 5 years (!), I am ashamed to admit) I am finally unclenching and releasing the Smoketest framework into the wild, ready or not. The code is published and will continue to be updated in a github repository. Documentation is still\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/Screen-Shot-2013-11-14-at-19.51.57-.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":3045,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/3045\/","url_meta":{"origin":3009,"position":2},"title":"Big Updates to Smoketest 2.x","date":"19 Dec 2020","format":false,"excerpt":"A little over a year ago, I released Smoketest 2.0, a complete re-write of the Smoketest unit testing framework first implemented some years ago. Other things then consumed my time, but in the past couple of months, Smoketest has rapidly progressed through no less than 4 (four!) fairly significant feature\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/vape_2.jpg?fit=1200%2C307&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":2185,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2185\/","url_meta":{"origin":3009,"position":3},"title":"Smoketest &#8211; Performance Case Visualisations","date":"22 Nov 2013","format":false,"excerpt":"This post is a peek behind the curtain of the next major update to Smoketest which I hope to have completed shortly: Performance Case visualisations. Smoketest has always had two types of test case that you could implement by deriving from two distinct base classes: TTestCase is the base class\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/Screen-Shot-2013-11-22-at-09.57.52.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":2095,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2095\/","url_meta":{"origin":3009,"position":4},"title":"Extending Smoketest (Part 1) &#8211; An Inspector Calls","date":"05 Nov 2013","format":false,"excerpt":"In the soon to be released Smoketest framework it is sometimes useful to create new test types to supplement the tests built-in to the framework. In this and the next post I will walk through the process of implementing and registering a custom test with the Smoketest framework. In a\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2111,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2111\/","url_meta":{"origin":3009,"position":5},"title":"Extending Smoketest (Part 2) &#8211; Great(er) Expectations","date":"07 Nov 2013","format":false,"excerpt":"In my previous post on Smoketest I showed how you can extend the inspections framework to work with complex types in your code. As promised, I shall now show how you can do much the same thing to extend the framework with entirely new tests. \u201cI must be taken as\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/3009"}],"collection":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/comments?post=3009"}],"version-history":[{"count":3,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/3009\/revisions"}],"predecessor-version":[{"id":3012,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/3009\/revisions\/3012"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media\/2957"}],"wp:attachment":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media?parent=3009"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/categories?post=3009"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/tags?post=3009"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}