<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Development Blog | OCERIS</title>
  <subtitle>Informative posts about all things related to software development.</subtitle>
  <link href="https://www.oceris.com/feeds/development.xml?utm_source=rss&amp;utm_medium=blog&amp;utm_campaign=rss-syndication" rel="self"/>
  <link href="https://www.oceris.com/blogs/development/"/>
  <updated>2021-09-10T00:00:00Z</updated>
  <id>https://www.oceris.com/blogs/development/</id>
  <author>
    <name>OCERIS</name>
    <email>support@oceris.com</email>
  </author>
  <entry>
    <title>How to use the DUnitX VCL GUI test runner for Delphi to run and view unit tests | OCERIS</title>
    <link href="https://www.oceris.com/blogs/development/dunitx-gui-test-runner/"/>
    <updated>2021-09-08T00:00:00Z</updated>
    <id>https://www.oceris.com/blogs/development/dunitx-gui-test-runner/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;https://github.com/VSoftTechnologies/DUnitX&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;DUnitX&lt;/a&gt; is an excellent unit test framework for Delphi created by Vincent Parrett who created the equally excellent products &lt;a href=&quot;https://www.finalbuilder.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;FinalBuilder and Continua CI&lt;/a&gt;. I had written my own test framework but found it lacking compared to the more fully developed DUnitX. I ended up adopting DUnitX for all my unit test projects for Delphi. The only thing I found myself missing was the GUI that I had developed for my framework. After some consideration, I decided to port what I had to work with DUnitX. I primarily created this post to address converting existing console based projects to use the GUI runner instead. Even though DUnitX is now included with Delphi, there isn’t much documentation on the steps to actually get the GUI runner up and running.&lt;/p&gt;
&lt;h2&gt;Option 1: Create a New Project&lt;/h2&gt;
&lt;p&gt;One thing that was updated after adding the new runner was the project wizard that creates DUnitX projects. Selecting &lt;code&gt;DUnitX Project&lt;/code&gt; from the &lt;code&gt;File-&amp;gt;New&lt;/code&gt; dialog in Delphi will show the wizard - which has an option for the VCL runner built-in.&lt;/p&gt;
&lt;div class=&quot;markdown-img max-w-md&quot; style=&quot;&quot;&gt;&lt;picture&gt;
    &lt;source type=&quot;image/webp&quot; srcset=&quot;https://www.oceris.com/images/blog-dv-dunitx-gui-test-runner-new-project-510w.webp 510w&quot; sizes=&quot;(min-width: 1024px) 100vw, 50vw&quot;&gt;
  &lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://www.oceris.com/images/blog-dv-dunitx-gui-test-runner-new-project-510w.jpeg 510w&quot; sizes=&quot;(min-width: 1024px) 100vw, 50vw&quot;&gt;
    &lt;img src=&quot;https://www.oceris.com/images/blog-dv-dunitx-gui-test-runner-new-project-510w.jpeg&quot; width=&quot;510&quot; height=&quot;496&quot; alt=&quot;DUnitX New Project Wizard&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
  &lt;/picture&gt;&lt;/div&gt;
&lt;p&gt;Selecting it will generate the project code necessary to use the GUI runner by default.&lt;/p&gt;
&lt;h2&gt;Option 2: Convert an Existing Project&lt;/h2&gt;
&lt;p&gt;Converting an existing DUnitX project to use the GUI runner is fairly easy, just not thoroughly documented.&lt;/p&gt;
&lt;h3&gt;Step 1: Include the GUI PAS File in the Project Uses&lt;/h3&gt;
&lt;p&gt;Include &lt;code&gt;DUnitX.Logger.GUI.VCL&lt;/code&gt; near the top of the uses clause in your project’s &lt;code&gt;dpr&lt;/code&gt; file.&lt;/p&gt;
&lt;pre class=&quot;language-pascal&quot;&gt;&lt;code class=&quot;language-pascal&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;uses&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  SysUtils&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;  DUnitX&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Loggers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;GUI&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;VCL&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  DUnitX&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Loggers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Console&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  DUnitX&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Loggers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Xml&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;NUnit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  DUnitX&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TestFramework&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 2: Call the Run Procedure&lt;/h3&gt;
&lt;p&gt;Next, in the body of your project file (between &lt;code&gt;begin&lt;/code&gt; and &lt;code&gt;end&lt;/code&gt;) you’ll want to include:&lt;/p&gt;
&lt;pre class=&quot;language-pascal&quot;&gt;&lt;code class=&quot;language-pascal&quot;&gt;    DUnitX&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Loggers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;GUI&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;VCL&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Run&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token keyword&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The GUI runner pas file has all the logic to create the runner and start the tests in the &lt;code&gt;Run&lt;/code&gt; procedure.&lt;/p&gt;
&lt;h2&gt;Combining with Continuous Integration&lt;/h2&gt;
&lt;p&gt;These days, your project is probably running under continuous integration and will be reliant on the console runner of DUnitX. Using various conditionals, you can make a project that will work for just about every use case. Below is a sample of my common boilerplate for all my DUnitX projects.&lt;/p&gt;
&lt;pre class=&quot;language-pascal&quot;&gt;&lt;code class=&quot;language-pascal&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;program&lt;/span&gt; SyncBlock&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Tests&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token comment&quot;&gt;//&amp;lt;SyncBlock id=&quot;OCERIS.Delphi.DUnitX.Project.AboveUses&quot; version=&quot;Delphi.XE&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token directive marco property&quot;&gt;{$IFDEF CI}&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token directive marco property&quot;&gt;{$APPTYPE CONSOLE}&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token directive marco property&quot;&gt;{$ELSE}&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token directive marco property&quot;&gt;{$IFNDEF GUI}&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token directive marco property&quot;&gt;{$IFNDEF TESTINSIGHT}&lt;/span&gt;&lt;br&gt;      &lt;span class=&quot;token directive marco property&quot;&gt;{$APPTYPE CONSOLE}&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token directive marco property&quot;&gt;{$ENDIF}&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token directive marco property&quot;&gt;{$ENDIF}&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token directive marco property&quot;&gt;{$ENDIF}&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token directive marco property&quot;&gt;{$STRONGLINKTYPES ON}&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token directive marco property&quot;&gt;{$R *.res}&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token comment&quot;&gt;//&amp;lt;/SyncBlock&gt;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;uses&lt;/span&gt;&lt;br&gt;  FastMM4&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  SysUtils&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  DUnitX&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Loggers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;GUI&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;VCL&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  DUnitX&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Loggers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Console&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  DUnitX&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Loggers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Xml&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;NUnit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  DUnitX&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TestFramework&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token comment&quot;&gt;//&amp;lt;snip&gt; - project specific files here&lt;/span&gt;&lt;br&gt;  CodeSiteLogging&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token comment&quot;&gt;//&amp;lt;SyncBlock id=&quot;OCERIS.Delphi.DUnitX.Project.BelowUses&quot; version=&quot;Delphi.XE&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;br&gt;  runner &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ITestRunner&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  results &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; IRunResults&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  logger &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ITestLogger&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  nunitLogger &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ITestLogger&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;begin&lt;/span&gt;&lt;br&gt;  Assert&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;IgnoreCaseDefault &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token directive marco property&quot;&gt;{$IFDEF CI}&lt;/span&gt;&lt;br&gt;  CodeSiteManager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Enabled &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token directive marco property&quot;&gt;{$ELSE}&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token directive marco property&quot;&gt;{$IFDEF GUI}&lt;/span&gt;&lt;br&gt;    DUnitX&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Loggers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;GUI&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;VCL&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Run&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token keyword&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token directive marco property&quot;&gt;{$ENDIF}&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;span class=&quot;token directive marco property&quot;&gt;{$IFDEF TESTINSIGHT}&lt;/span&gt;&lt;br&gt;    TestInsight&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DUnitX&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RunRegisteredTests&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token keyword&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token directive marco property&quot;&gt;{$ENDIF}&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token directive marco property&quot;&gt;{$ENDIF}&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token comment&quot;&gt;//Check command line options, will exit if invalid&lt;/span&gt;&lt;br&gt;    TDUnitX&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CheckCommandLine&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token comment&quot;&gt;//Create the test runner&lt;/span&gt;&lt;br&gt;    runner &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; TDUnitX&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CreateRunner&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token comment&quot;&gt;//Tell the runner to use RTTI to find Fixtures&lt;/span&gt;&lt;br&gt;    runner&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UseRTTI &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token comment&quot;&gt;//tell the runner how we will log things&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token comment&quot;&gt;//Log to the console window&lt;/span&gt;&lt;br&gt;    logger &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; TDUnitXConsoleLogger&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Create&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;    runner&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AddLogger&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;logger&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token comment&quot;&gt;//Generate an NUnit compatible XML File&lt;/span&gt;&lt;br&gt;    nunitLogger &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; TDUnitXXMLNUnitFileLogger&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Create&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TDUnitX&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Options&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;XMLOutputFile&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;    runner&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AddLogger&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nunitLogger&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;    runner&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FailsOnNoAsserts &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//When true, Assertions must be made during tests;&lt;/span&gt;&lt;br&gt;&lt;br&gt;    &lt;span class=&quot;token comment&quot;&gt;//Run tests&lt;/span&gt;&lt;br&gt;    results &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; runner&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Execute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;not&lt;/span&gt; results&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AllPassed &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;&lt;br&gt;      System&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ExitCode &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; EXIT_ERRORS&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token keyword&quot;&gt;on&lt;/span&gt; E&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Exception &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;&lt;br&gt;      System&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Writeln&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ClassName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;: &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; E&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;Message&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;span class=&quot;token directive marco property&quot;&gt;{$IFNDEF CI}&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token comment&quot;&gt;//We don&#39;t want this happening when running under CI.&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; TDUnitX&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Options&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ExitBehavior &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TDUnitXExitBehavior&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Pause &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;begin&lt;/span&gt;&lt;br&gt;    System&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Done...  Press &amp;lt;Enter&gt; key to quit.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;    System&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Readln&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token directive marco property&quot;&gt;{$ENDIF}&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token comment&quot;&gt;//&amp;lt;/SyncBlock&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Switching to the GUI runner isn’t hard - you just have to know what pieces to put where. Making it co-exist with CI is also pretty simple once you have a working example. Hopefully the above information will make it a bit easier to do both.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Speed up your TypeScript or JavaScript Jest unit tests with these simple changes | OCERIS</title>
    <link href="https://www.oceris.com/blogs/development/speed-up-your-jest-tests/"/>
    <updated>2021-09-10T00:00:00Z</updated>
    <id>https://www.oceris.com/blogs/development/speed-up-your-jest-tests/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;https://jestjs.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Jest&lt;/a&gt; is my current choice for unit testing JavaScript and TypeScript projects (using &lt;a href=&quot;https://kulshekhar.github.io/ts-jest/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ts-jest&lt;/a&gt;). I particularly like that it has everything baked in and does not require separate assertion or mock libraries. However, one thing that I was not particularly fond of was the speed.&lt;/p&gt;
&lt;h2&gt;The Problem&lt;/h2&gt;
&lt;p&gt;On a recent TypeScript project (a small library of utility functions), I started to notice that my unit tests were taking much longer than expected. This project is new, relatively small, an only contained 38 unit tests across 5 files. The run would consistently take over 16 seconds to complete on a development machine with extremely high-end specs.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;Test Suites: &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; passed, &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; total&lt;br&gt;Tests:       &lt;span class=&quot;token number&quot;&gt;38&lt;/span&gt; passed, &lt;span class=&quot;token number&quot;&gt;38&lt;/span&gt; total&lt;br&gt;Snapshots:   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; total&lt;br&gt;Time:        &lt;span class=&quot;token number&quot;&gt;16.586&lt;/span&gt; s&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I tried a lot of things in my &lt;code&gt;jest.config.ts&lt;/code&gt; file, including limiting the search folder to only look in my &lt;code&gt;src&lt;/code&gt; directory, and even reordered the &lt;code&gt;moduleFileExtensions&lt;/code&gt; to include TypeScript files first per the &lt;a href=&quot;https://jestjs.io/docs/configuration#modulefileextensions-arraystring&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Jest documentation&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; InitialOptionsTsJest &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;ts-jest/dist/types&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; config&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; InitialOptionsTsJest &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  globals&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&#39;ts-jest&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;&lt;br&gt;  preset&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;ts-jest&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  displayName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;OSAS-TypeScript&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  testEnvironment&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;node&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  roots&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&amp;lt;rootDir&gt;/src/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  testMatch&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;**/*.Tests.ts?(x)&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  moduleFileExtensions&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;ts&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;tsx&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;jsx&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;json&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;node&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; config&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The file above is what I ended up with, but the tests still took around 16 seconds to run.&lt;/p&gt;
&lt;h2&gt;The Solution&lt;/h2&gt;
&lt;p&gt;After much searching, I found a lot of people have the same issue, and a lot of suggestions of things to try. Most actually didn’t have any affect on the speed, but two configuration changes did.&lt;/p&gt;
&lt;p&gt;I modified my &lt;code&gt;jest.config.ts&lt;/code&gt; file with the two options highlighted:&lt;/p&gt;
&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; InitialOptionsTsJest &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;ts-jest/dist/types&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; config&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; InitialOptionsTsJest &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  globals&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&#39;ts-jest&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      isolatedModules&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  preset&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ts-jest&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  displayName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;OSAS-TypeScript&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  testEnvironment&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  roots&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;rootDir&gt;/src/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  testMatch&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;**/*.Tests.ts?(x)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  moduleFileExtensions&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tsx&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;jsx&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;json&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;  maxWorkers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;50%&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; config&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Just those changes yielded a &lt;strong&gt;95% increase in speed&lt;/strong&gt; with the test run now consistently running in under a second.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;Test Suites: &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; passed, &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; total&lt;br&gt;Tests:       &lt;span class=&quot;token number&quot;&gt;38&lt;/span&gt; passed, &lt;span class=&quot;token number&quot;&gt;38&lt;/span&gt; total&lt;br&gt;Snapshots:   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; total&lt;br&gt;Time:        &lt;span class=&quot;token number&quot;&gt;0.767&lt;/span&gt; s&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;So What’s the Catch?&lt;/h2&gt;
&lt;h3&gt;maxWorkers: “50%”&lt;/h3&gt;
&lt;p&gt;There isn’t really a catch to this setting. It reduces the default number of simultaneous threads used to run tests which, in most cases, yields better performance. In fact, in most cases it yields a 20% increase in performance by itself.&lt;/p&gt;
&lt;h3&gt;isolatedModules: true&lt;/h3&gt;
&lt;p&gt;This setting does have a significant caveat - it compiles each file separately which disables type-checking and some other features but, as you can see, results in a huge performance boost. This may or may not be what is needed for your project, so use accordingly.&lt;/p&gt;
</content>
  </entry>
</feed>