<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Symflower</title>
    <description>The latest articles on DEV Community by Symflower (@symflower).</description>
    <link>https://dev.to/symflower</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F830914%2Fc018d023-7f68-41fc-923d-0123a4e78613.jpg</url>
      <title>DEV Community: Symflower</title>
      <link>https://dev.to/symflower</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/symflower"/>
    <language>en</language>
    <item>
      <title>Isolating IntelliJ plugin tests using temporary project directories</title>
      <dc:creator>Symflower</dc:creator>
      <pubDate>Mon, 16 Jan 2023 08:40:17 +0000</pubDate>
      <link>https://dev.to/symflower/isolating-intellij-plugin-tests-using-temporary-project-directories-4bh6</link>
      <guid>https://dev.to/symflower/isolating-intellij-plugin-tests-using-temporary-project-directories-4bh6</guid>
      <description>&lt;p&gt;When testing a plugin for IntelliJ-based IDEs using a UI test, the plugin gets to operate within a fully-featured instance of the IDE. &lt;strong&gt;Most tests will therefore require a project to perform their actions on.&lt;/strong&gt; This opens a question: How do you deal with modifications to test projects made by tests? Add undo logic at the end of every test? Revert using a version control system? &lt;strong&gt;Those options sound like easy ways to make new mistakes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We faced the same problem when writing tests for our own plugin, &lt;a href="https://plugins.jetbrains.com/plugin/18944-symflower" rel="noopener noreferrer"&gt;Symflower for IntelliJ IDEA and GoLand&lt;/a&gt;, but &lt;strong&gt;we've opted for a simpler solution&lt;/strong&gt;. We don't run tests on the canonical source of our test projects but rather copy the entire project directory and use that copy instead. This avoids relying on repetitive cleanup logic or VCS-based reverting that could undo legitimate changes to the source files.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Curious about how we do it? Head over to Symflower's blog to read the rest of this article:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://symflower.com/en/company/blog/2023/intellij-temporary-project-directories/" rel="noopener noreferrer"&gt;&lt;strong&gt;Isolating IntelliJ plugin tests using temporary project directories&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Accessing IntelliJ plugin classes in UI tests</title>
      <dc:creator>Symflower</dc:creator>
      <pubDate>Tue, 10 Jan 2023 11:29:47 +0000</pubDate>
      <link>https://dev.to/symflower/accessing-intellij-plugin-classes-in-ui-tests-4514</link>
      <guid>https://dev.to/symflower/accessing-intellij-plugin-classes-in-ui-tests-4514</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oadlrHsr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4blxajjth725d4ngv5vg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oadlrHsr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4blxajjth725d4ngv5vg.png" alt="Accessing IntelliJ plugin classes in UI tests" width="880" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When testing an IntelliJ plugin&lt;/strong&gt;, you'll likely &lt;strong&gt;reach for UI tests to verify that both the user interface as well as the code behind it functions correctly&lt;/strong&gt;. In UI tests, your plugin runs in a real instance of IntelliJ that is similar to a production environment on a user's machine. &lt;strong&gt;That increases your end-to-end coverage&lt;/strong&gt; but sometimes it's harder to verify success conditions for a test in that environment. So as a last resort, you might want to call into a service that's part of the plugin to verify some internal state directly.&lt;/p&gt;

&lt;p&gt;For example, we found for our &lt;a href="https://plugins.jetbrains.com/plugin/18944-symflower"&gt;Symflower plugin&lt;/a&gt;, we needed this to check for progress indicators displayed by our plugin. &lt;strong&gt;We could not verify our plugin's progress indicators purely from the UI because they were too fast for the UI automation to pick them up.&lt;/strong&gt; So we had to build a service into our plugin that, when run under test, keeps references to shown progress indicators to allow tests to verify them. But how would one go about doing that?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;To find out, &lt;a href="https://symflower.com/en/company/blog/2023/intellij-plugin-classes-in-tests/"&gt;read the rest of this post on Symflower’s blog!&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>intellij</category>
      <category>plugin</category>
    </item>
    <item>
      <title>What is new in Java 20?</title>
      <dc:creator>Symflower</dc:creator>
      <pubDate>Thu, 24 Nov 2022 15:10:03 +0000</pubDate>
      <link>https://dev.to/symflower/what-is-new-in-java-20-21gh</link>
      <guid>https://dev.to/symflower/what-is-new-in-java-20-21gh</guid>
      <description>&lt;p&gt;Java 20 is &lt;a href="https://openjdk.org/projects/jdk/20/" rel="noopener noreferrer"&gt;due for release in March 2023&lt;/a&gt;, and is expected to introduce &lt;a href="https://jdk.java.net/20/release-notes" rel="noopener noreferrer"&gt;a range of changes and new functionality&lt;/a&gt;. We prepared &lt;strong&gt;a sneak peek into which JEPs are most likely to be accepted into JDK 20&lt;/strong&gt;, and which ones we are excited to hopefully be accepted next!&lt;/p&gt;

&lt;p&gt;The latest version of the JDK (Java Development Kit) 19 was released on the 20th September 2022. The next version, Java 20, &lt;a href="https://www.oracle.com/java/technologies/java-se-support-roadmap.html" rel="noopener noreferrer"&gt;is planned as a non-LTS release&lt;/a&gt;, while the following version 21 is set to be a release with Long-Term Support (LTS). The upcoming version 20 is expected to bring a number of great updates, so we're excited to get our hands on it in March!&lt;/p&gt;

&lt;p&gt;But before we jump into the JEPs lined up for Java 20, let's do &lt;strong&gt;a quick overview of the process for updating Java&lt;/strong&gt; and the concept of enhancement proposals so that you have the full picture on what's going on.&lt;/p&gt;

&lt;h2&gt;
  
  
  JDK Enhancement Proposal (JEP) &amp;amp; roadmap process
&lt;/h2&gt;

&lt;p&gt;Development of the Java Development Kit (JDK) is based on the concept of &lt;a href="https://en.wikipedia.org/wiki/JDK_Enhancement_Proposal" rel="noopener noreferrer"&gt;JDK Enhancement Proposals&lt;/a&gt;, or JEPs. In essence, &lt;strong&gt;these enhancement proposals serve as the roadmap for JDK release projects and all related development activities&lt;/strong&gt;. The JEP process &lt;strong&gt;does not replace the Java community process&lt;/strong&gt; as that is still the primary way to approve changes in the Java API and language. Rather, Oracle's intention for introducing the JEPs back in 2010 was to enable OpenJDK contributors to submit ideas to improve the ecosystem. JEPs help track the development status of features intended for delivery in a JDK release project, as well as work that is not linked to a specific release.&lt;/p&gt;

&lt;p&gt;At the time of writing, the JEP Index lists 437 enhancement proposals, as well as a number of draft and submitted JEPs. Of all these enhancement proposals, the first 4 are meta-JEPs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://openjdk.org/jeps/0" rel="noopener noreferrer"&gt;&lt;strong&gt;JEP 0&lt;/strong&gt;&lt;/a&gt; is the JEP Index of all posted proposals referenced above.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://openjdk.org/jeps/1" rel="noopener noreferrer"&gt;&lt;strong&gt;JEP 1&lt;/strong&gt;&lt;/a&gt; outlines the process for managing (collecting, reviewing, prioritizing &amp;amp; evaluating, and recording the results) of proposals for JDK enhancement, process, and infrastructure improvements.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://openjdk.org/jeps/2" rel="noopener noreferrer"&gt;&lt;strong&gt;JEP 2&lt;/strong&gt;&lt;/a&gt; is a template to be used for creating new JEPs.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://openjdk.org/jeps/3" rel="noopener noreferrer"&gt;&lt;strong&gt;JEP 3&lt;/strong&gt;&lt;/a&gt; describes the JDK release process.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The output of the &lt;a href="http://cr.openjdk.java.net/~mr/jep/jep-2.0-02.html" rel="noopener noreferrer"&gt;JEP process&lt;/a&gt; is a JDK roadmap that contains proposals for new features as well as other improvement ideas to be considered for inclusion in JDK release projects. The roadmap basically serves as a backlog, covering ideas for at least the next three years, &lt;strong&gt;so not all JEPs will make it into the next release&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp69g93juzy0sg3qewj8q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp69g93juzy0sg3qewj8q.png" alt="Workflow of the revised JEP Process&amp;lt;br&amp;gt;
" width="612" height="299"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Source: &lt;a href="http://cr.openjdk.java.net/%7Emr/jep/jep-2.0-fi.png" rel="noopener noreferrer"&gt;http://cr.openjdk.java.net/~mr/jep/jep-2.0-fi.png&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can check out the current list of JEPs (drafts and submitted candidates) for Java 20 on the &lt;a href="https://openjdk.org/jeps/0" rel="noopener noreferrer"&gt;JEP 0&lt;/a&gt;, as well as the &lt;a href="https://jdk.java.net/20/release-notes" rel="noopener noreferrer"&gt;Early-Access Release Notes&lt;/a&gt; for changes of this version. OK, now that you understand the process, let's dive right into what JEPs are expected to make it into Java 20!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://symflower.com/en/company/blog/2022/what-is-new-in-java-20/" rel="noopener noreferrer"&gt;Read the rest of this post&lt;/a&gt; over at Symflower's blog!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>Software Testing Trends for 2023</title>
      <dc:creator>Symflower</dc:creator>
      <pubDate>Thu, 17 Nov 2022 14:39:09 +0000</pubDate>
      <link>https://dev.to/symflower/software-testing-trends-for-2023-38dp</link>
      <guid>https://dev.to/symflower/software-testing-trends-for-2023-38dp</guid>
      <description>&lt;p&gt;With software becoming the main value driver and the primary interface between developers and customers, focus on software quality is growing. The need to deliver high-quality, bug-free products in ever-accelerating cycles is putting pressure on software teams. Software testing has to apply new methods to keep pace. Here's a list of new testing strategies that are gaining ground in 2023, and which software testing trends Symflower expects to continue to unfold this coming year!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Continue reading on Symflower's blog:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://symflower.com/en/company/blog/2022/software-testing-trends-2023/"&gt;&lt;strong&gt;Software testing trends for 2023&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>softwaretesting</category>
      <category>testing</category>
      <category>trends</category>
    </item>
    <item>
      <title>Software Development Trends for 2023</title>
      <dc:creator>Symflower</dc:creator>
      <pubDate>Wed, 16 Nov 2022 20:44:25 +0000</pubDate>
      <link>https://dev.to/symflower/software-development-trends-for-2023-4kja</link>
      <guid>https://dev.to/symflower/software-development-trends-for-2023-4kja</guid>
      <description>&lt;p&gt;As software is taking over the world, the development strategies we use have to evolve in lockstep to keep pace. With development teams constantly looking to innovate and improve their efficiency, there are a few defining software development trends emerging that will influence how we deliver software in 2023 and beyond.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;To find out about the key trends defining software development in 2023, continue reading on Symflower's blog:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://symflower.com/en/company/blog/2022/software-development-trends-2023/" rel="noopener noreferrer"&gt;&lt;strong&gt;Software development trends for 2023&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Java Fuzzing with Jazzer compared to Symflower</title>
      <dc:creator>Symflower</dc:creator>
      <pubDate>Tue, 15 Nov 2022 11:23:36 +0000</pubDate>
      <link>https://dev.to/symflower/java-fuzzing-with-jazzer-compared-to-symflower-57lb</link>
      <guid>https://dev.to/symflower/java-fuzzing-with-jazzer-compared-to-symflower-57lb</guid>
      <description>&lt;p&gt;Fuzzing is a &lt;strong&gt;testing technique where random values are generated as inputs to find unexpected behavior&lt;/strong&gt; such as crashes and security issues. Previously we &lt;a href="https://symflower.com/en/company/blog/2022/go-beta-fuzzing-vs-symflower/"&gt;looked at the new Golang release 1.18 which includes native fuzzing&lt;/a&gt; and our Core Technology blog series contained a post that &lt;a href="https://symflower.com/en/company/blog/2022/methods-for-automated-test-value-generation/"&gt;compares symbolic execution to different other testing techniques&lt;/a&gt;, including fuzzing. Today, we will dive into the Java world and check out the most popular Java fuzzing solution: &lt;a href="https://github.com/CodeIntelligenceTesting/jazzer"&gt;Jazzer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We will explore how &lt;strong&gt;Jazzer is used to automatically generate malicious inputs for Java programs&lt;/strong&gt;, and how it compares to &lt;strong&gt;&lt;a href="https://dev.to/en/products/symflower-cli/vscode-java/"&gt;Symflower&lt;/a&gt;, which can automatically generate unit tests to uncover bugs and errors in your code&lt;/strong&gt;. With the help of Jazzer, many bugs - some of them even in the OpenJDK - were found already. Also, as of March 2021, &lt;a href="https://security.googleblog.com/2021/03/fuzzing-java-in-oss-fuzz.html"&gt;Jazzer is officially part of OSS-Fuzz&lt;/a&gt;, Google's &lt;a href="https://github.com/google/oss-fuzz"&gt;cloud fuzzing engine&lt;/a&gt;. It should be noted that Jazzer is a pure "bug detection" utility that finds reproducers for errors in user code. Symflower can do the same, but provides additional functionalities to boost developer productivity, like generating high coverage unit tests and providing &lt;a href="https://symflower.com/en/company/blog/2022/less-boiler-plate-with-java-test-templates/"&gt;test templates&lt;/a&gt; for the software developer or tester.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tool Setup
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;We will now go through the process of installing both Symflower and Jazzer so you can easily follow along on your local machine.&lt;/strong&gt; First, we create a new folder &lt;code&gt;fuzz&lt;/code&gt; where we can place everything we need.&lt;/p&gt;

&lt;p&gt;For Symflower, we can just head over to &lt;a href="https://dev.to/en/products/symflower-cli/vscode-java/"&gt;get.symflower.com&lt;/a&gt; to install either the CLI version or an IDE plugin. No matter which version we choose, we just need to run the installer and are immediately good to go.&lt;/p&gt;

&lt;p&gt;To install Jazzer, we need to download the executable and its dependencies from the &lt;a href="https://github.com/CodeIntelligenceTesting/jazzer/releases"&gt;GitHub releases page&lt;/a&gt;. We then extract &lt;code&gt;jazzer&lt;/code&gt;, &lt;code&gt;jazzer_agent_deploy.jar&lt;/code&gt; and &lt;code&gt;jazzer_api_deploy.jar&lt;/code&gt; into our &lt;code&gt;fuzz&lt;/code&gt; folder to have them at the ready. For a permanent installation, we'd need to move these files to where our &lt;code&gt;PATH&lt;/code&gt; and Java can pick up on them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example 1: Validating a username
&lt;/h2&gt;

&lt;p&gt;Let's look at a very simple example first, to get a feel for how the different tools are used. We assume that we have some user database or login system and want to make sure that the usernames consist of only lowercase letters. From this snippet we can see that we just loop over all characters in the input string and throw an &lt;code&gt;IllegalArgumentException&lt;/code&gt; when we encounter an invalid character.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// fuzz/example1/Strings.java&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Strings&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;validateName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;charAt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="sc"&gt;'a'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="sc"&gt;'z'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"name must consist of letters"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Jazzer has an "autofuzz" feature that automatically scans the code one wants to analyze and properly matches the input data types to the program input.&lt;/strong&gt; In this case we will only tell it that we want to analyze our &lt;code&gt;validateName&lt;/code&gt; function and it will automatically figure out that it has to generate random strings as inputs. One downside of Jazzer's "autofuzz" mode, however, is that it only detects unexpected Exceptions from the user code. Here though, we actually expect that there are problems with invalid names since we added a &lt;code&gt;throws IllegalArgumentException&lt;/code&gt; to the method body.&lt;/p&gt;

&lt;p&gt;This tells Jazzer that &lt;code&gt;IllegalArgumentException&lt;/code&gt;s are fine for us, so no test cases fulfilling the condition &lt;code&gt;c &amp;lt; 'a' || c &amp;gt; 'z'&lt;/code&gt; will be generated. As the behavior of only looking for unexpected exceptions cannot be deactivated for Jazzer, we must add a little hack to actually provoke full coverage of the function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;hashCode&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// throw new IllegalArgumentException("name must consist of letters");&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To analyze this version with Jazzer then, we first need to compile the code with &lt;code&gt;javac fuzz/example1/Strings.java&lt;/code&gt;, then we can execute the fuzzer by running &lt;code&gt;./jazzer --cp=$PWD/fuzz/example1 --autofuzz=Strings::validateName&lt;/code&gt;. We will see that two files &lt;code&gt;Crash-&amp;lt;hash&amp;gt;&lt;/code&gt; are immediately generated, and the fuzzer keeps going, generating more and more random input strings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Crash_b6334b553dfdbd68c65c21aa59b75ae8dafc02ca&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Throwable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;validateName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Crash_da39a3ee5e6b4b0d3255bfef95601890afd80709&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Throwable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;validateName&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This shows that Jazzer successfully generated an input that provokes the exception, and additionally found the case where a "null" string is used. After half a minute, the fuzzer gives up to generate more values and terminates with an "out of memory" message. Many more random strings were constructed but none resulted in additional interesting behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With Symflower, we can just run the tool without any additional modifications necessary.&lt;/strong&gt; This is done by either executing the &lt;code&gt;symflower&lt;/code&gt; command in the console in our "fuzz/example1" directory, or - if we have an IDE plugin installed - triggering Symflower right from your IDE. The automatic unit test generation takes roughly a few seconds and results in a file &lt;code&gt;StringsSymflowerTest.java&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Test&lt;/span&gt; &lt;span class="c1"&gt;// (expected = NullPointerException.class)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;validateName1&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;validateName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;validateName2&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;validateName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Test&lt;/span&gt; &lt;span class="c1"&gt;// (expected = IllegalArgumentException.class)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;validateName3&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"\u0001"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;validateName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;validateName4&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"z"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;validateName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Test&lt;/span&gt; &lt;span class="c1"&gt;// (expected = IllegalArgumentException.class)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;validateName5&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"\u00ef"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;validateName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Symflower result also includes the cases where a non-letter and a "null" string is present. Though, since these are unit tests, we also have cases that don't provoke any error but simply exercise our whole example code. While Jazzer found the errors too, Symflower additionally computed a complete test suite for our example with additional information on the outcomes.&lt;/p&gt;

&lt;p&gt;Jazzer found cases for the problems very fast. However, it continued trying to find additional ones, even though there are none. Symflower on the other hand finished fast with this example. However, it could be faster. We are working hard on improving the performance of Symflower, so if you find some example that takes a while to process, please let us know through our &lt;a href="https://github.com/symflower/symflower/issues"&gt;public issue tracker&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example 2: Modeling a simple train station
&lt;/h2&gt;

&lt;p&gt;Now, we present &lt;strong&gt;a more complex scenario where we model a train station and different types of trains&lt;/strong&gt;. We check if the station can accept a request to have a train stop, and depending on the type of the train, some conditions have to apply for the train to be allowed to stop at the station.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Train&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FreightTrain&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Train&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PassengerTrain&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Train&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Station&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;weightLimit&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;lengthLimit&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;accept&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Train&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;PassengerTrain&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;PassengerTrain&lt;/span&gt; &lt;span class="n"&gt;pt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PassengerTrain&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lengthLimit&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"train cannot safely stop within station borders"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;FreightTrain&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;FreightTrain&lt;/span&gt; &lt;span class="n"&gt;ft&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FreightTrain&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weightLimit&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ft&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"train cannot safely use the station tracks"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"unknown train type"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As before, we need to manually provoke a "NullPointerException" for Jazzer to pick up on our unwanted states.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;hashCode&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// throw new IllegalArgumentException("&amp;lt;error message&amp;gt;");&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We note that for Jazzer's "autofuzz" functionality, &lt;strong&gt;it is necessary that all of these classes are &lt;code&gt;public&lt;/code&gt;, so they need to be placed into their own respective files&lt;/strong&gt; in &lt;code&gt;fuzz/example2&lt;/code&gt;. Then, we must again compile our code with &lt;code&gt;javac fuzz/example2/*.java&lt;/code&gt; before we can start the fuzzer with &lt;code&gt;./jazzer --cp=$PWD/fuzz/example2 --autofuzz=Station::accept&lt;/code&gt;. The fuzzer starts generating values, but won't find the more interesting critical inputs any time soon. However, we see that the simple "null" case is present:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Crash_adc83b19e793491b1c6ea0fd8b46cd9f32e592fc&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Throwable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;(((&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;function&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Supplier&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Station&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;)&lt;/span&gt; &lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Station&lt;/span&gt; &lt;span class="n"&gt;autofuzzVariable0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Station&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;autofuzzVariable0&lt;/span&gt;&lt;span class="o"&gt;;})).&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;accept&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="nc"&gt;Train&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the meantime (in another terminal window) we can check how Symflower performs. We just run &lt;code&gt;symflower&lt;/code&gt; in the &lt;code&gt;fuzz/example2&lt;/code&gt; directory, or - if we're working with an IDE plugin - trigger the analysis from within the IDE. Within seconds, we obtain the following test cases.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Test&lt;/span&gt; &lt;span class="c1"&gt;// (expected = IllegalArgumentException.class)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;accept1&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Station&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Station&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="nc"&gt;Train&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;accept&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;accept2&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Station&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Station&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="nc"&gt;Train&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FreightTrain&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;accept&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;accept3&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Station&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Station&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="nc"&gt;Train&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PassengerTrain&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;accept&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nd"&gt;@Test&lt;/span&gt; &lt;span class="c1"&gt;// (expected = IllegalArgumentException.class)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;accept4&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Station&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Station&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lengthLimit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Train&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PassengerTrain&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;accept&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nd"&gt;@Test&lt;/span&gt; &lt;span class="c1"&gt;// (expected = IllegalArgumentException.class)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;accept5&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Station&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Station&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;weightLimit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Train&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FreightTrain&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;accept&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see that Symflower found both interesting cases, a freight train that is too heavy and a passenger train that's too long, but also generated tests for the remaining cases.&lt;/p&gt;

&lt;p&gt;Jazzer however, seems to struggle with the custom data types we introduced. &lt;strong&gt;We need to aid Jazzer with these data types by writing a custom test driver&lt;/strong&gt; &lt;code&gt;fuzz/example2/Fuzzer.java&lt;/code&gt;. For this, we must pick which train type we want to check, so we choose the &lt;code&gt;PassengerTrain&lt;/code&gt;. If we want to check both cases, we would need to add another test driver. But one case should suffice to demonstrate the process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.code_intelligence.jazzer.api.FuzzedDataProvider&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Fuzzer&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;fuzzerTestOneInput&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FuzzedDataProvider&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Station&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Station&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lengthLimit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;consumeInt&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;PassengerTrain&lt;/span&gt; &lt;span class="n"&gt;pt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PassengerTrain&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;pt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;consumeInt&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;accept&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pt&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To compile the code now, we need to add the Jazzer API &lt;code&gt;javac -cp ".:./jazzer_api_deploy.jar" fuzz/example2/*.java&lt;/code&gt;. We don't use the "autofuzz" feature anymore, but directly point Jazzer to the test driver using &lt;code&gt;./jazzer --cp=$PWD/fuzz/example2/ --target_class=Fuzzer&lt;/code&gt;. This time we instantly obtain a crashing input, but only for the "PassengerTrain" case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.lang.reflect.InvocationTargetException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.lang.reflect.Method&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Crash_adc83b19e793491b1c6ea0fd8b46cd9f32e592fc&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;base64Bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;join&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"rO0ABXNyABNqYXZhLnV0aWwuQXJyYXlMaXN0eIHSHZnHYZ0DAAFJAARzaXpleHAAAAACdwQAAAACc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAApzcQB+AAIAAAAAeA=="&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Throwable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;ClassLoader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getSystemClassLoader&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;setDefaultAssertionStatus&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;Method&lt;/span&gt; &lt;span class="n"&gt;fuzzerInitialize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Fuzzer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMethod&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"fuzzerInitialize"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;fuzzerInitialize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;invoke&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;NoSuchMethodException&lt;/span&gt; &lt;span class="n"&gt;ignored&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;Method&lt;/span&gt; &lt;span class="n"&gt;fuzzerInitialize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Fuzzer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMethod&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"fuzzerInitialize"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[].&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;fuzzerInitialize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;invoke&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;NoSuchMethodException&lt;/span&gt; &lt;span class="n"&gt;ignored1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IllegalAccessException&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;InvocationTargetException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printStackTrace&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
                &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;exit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IllegalAccessException&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;InvocationTargetException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printStackTrace&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;exit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;code_intelligence&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jazzer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CannedFuzzedDataProvider&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;code_intelligence&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jazzer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CannedFuzzedDataProvider&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base64Bytes&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Fuzzer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fuzzerTestOneInput&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The test case is quite complex, since Jazzer models both input values as a random string.&lt;/strong&gt; This string is then converted to the two input integers for the length limit and train length, but &lt;strong&gt;we cannot be sure which actual integer values are chosen here&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So as we see, there are some caveats when working with Jazzer and custom data types, requiring manual work to supply the fuzzer with the correct test drivers, and being able to understand the generated test values. Symflower on the other hand generated a complete test suite fast and presents easy to understand test cases. However, we are still not done: if you find code that does not work for you or has results that could be done better, please let us know through our &lt;a href="https://github.com/symflower/symflower/issues"&gt;public issue tracker&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;By the way, there is an additional bug in the examples above. Were you able to spot it? If so, how? By looking at the code or the test case?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;Symflower is an easy-to-apply, out-of-the-box solution that generates unit test suites but also increases developer productivity through functionalities like test templates. Jazzer, on the other hand, specializes on efficiently generating input values to trigger bugs and errors in user code. Both of these tools are free and focus on improving your development experience - so why not just use both of them? 🤔&lt;/p&gt;

&lt;p&gt;We are working hard on providing the best overall solution for generating inputs for bug detection and unit testing. And, we're improving Symflower every day so feel free to check it out and report your experience back to us - we're always happy to receive your feedback!&lt;/p&gt;

&lt;p&gt;To be notified of any new blog posts regarding coding, testing, features of Symflower or the memes, feel free to subscribe to our newsletter. You can also follow us on social media and - if this post helped you - share it via &lt;a href="https://twitter.com/symflower"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.linkedin.com/company/symflower"&gt;LinkedIn&lt;/a&gt; or &lt;a href="https://www.facebook.com/symflower"&gt;Facebook&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>java</category>
      <category>fuzzing</category>
      <category>jazzer</category>
    </item>
    <item>
      <title>Integrating a Language Server (LSP) in a VS Code Extension</title>
      <dc:creator>Symflower</dc:creator>
      <pubDate>Thu, 10 Nov 2022 13:28:21 +0000</pubDate>
      <link>https://dev.to/symflower/integrating-a-language-server-lsp-in-a-vs-code-extension-f15</link>
      <guid>https://dev.to/symflower/integrating-a-language-server-lsp-in-a-vs-code-extension-f15</guid>
      <description>&lt;p&gt;If you’re working on developer assistance tooling such as auto-completion or error highlighting for a particular programming language, you probably want the functionality with more than one code editor. In the bad old days this used to be quite labor-intensive: developers had to come up with ways to share common logic across different editor platforms and technologies and write repetitive glue code for every integration. The Language Server Protocol (LSP) was invented to solve this problem.&lt;/p&gt;

&lt;p&gt;LSP standardizes interactions between developer tooling (referred to as “servers” in the protocol) and text editors (“clients”) over a technology-neutral base layer. This completely decouples clients from servers meaning that you, as a tooling author, don’t have to write tons of glue code when targeting an editor that supports LSP. Plus, you can write your server in any language you like without having to worry about inter-process communication. LSP was first introduced in Visual Studio Code but it’s supported by a &lt;a href="https://microsoft.github.io/language-server-protocol/implementors/tools/"&gt;decent number of editors&lt;/a&gt; by now.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does LSP work?
&lt;/h3&gt;

&lt;p&gt;LSP runs over remote procedure calls using the JSON-RPC protocol (more specifically, version two of JSON-RPC). In JSON-RPC one client and one server exchange messages that either describe a request, response, or notification. Requests can be thought of as function calls with a given set of arguments that require a response. Responses either carry a return value or an error. Notifications are similar to requests, except that they don’t require a response from the other party, so they’re completely asynchronous. An example JSON-RPC request to add two numbers could look like this:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{ "jsonrpc": "2.0", "id": 1, "method": "add", "params": { "a": 2, "b": 3 } }&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Followed by a response:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{ "jsonrpc": "2.0", "id": 1, "result": 5 }&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Despite using the terms “client” and “server”, the protocol is entirely bidirectional. It requires a bidirectional communication channel to transmit messages, which could be anything from WebSockets to raw TCP connections, or Unix domain sockets. The LSP specification includes &lt;a href="https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#implementationConsiderations"&gt;recommendations for handling communication channels&lt;/a&gt;. In practice, many language servers use standard input and output. The specification also describes the &lt;a href="https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#baseProtocol"&gt;RPC layer in more detail&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On top of JSON-RPC, LSP defines a set of standard requests and notifications for servers to expose certain features to clients. The list of requests is quite long but the &lt;a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current"&gt;specification&lt;/a&gt; does a good job categorizing and explaining all of them. Here are some requests that we implement in the &lt;a href="https://symflower.com/"&gt;Symflower&lt;/a&gt; language server:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;textDocument/didSave&lt;/code&gt; for triggering an analysis followed by unit test generation when a source file is saved in the editor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;workspace/didChangeWorkspaceFolders&lt;/code&gt; for keeping track of directories that should be included in future analyses.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;textDocument/codeLens&lt;/code&gt; and &lt;code&gt;workspace/executeCommand&lt;/code&gt; for letting users interactively add generated unit tests to their test files in our &lt;a href="https://symflower.com/en/company/blog/2022/test-review-workflow/"&gt;“test review” mode&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;codeLens&lt;/code&gt; request returns definitions for code lenses with commands to invoke when a user interacts with them in the client (usually by clicking).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;executeCommand&lt;/code&gt; is called when a command is then invoked (i.e. when a user actually clicks on a code lens).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Starting a language server from a VS Code extension
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Continue reading on Symflower's blog:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://symflower.com/en/company/blog/2022/lsp-in-vscode-extension/"&gt;&lt;strong&gt;Integrating a language server (LSP) in a VS Code extension&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>vscode</category>
      <category>lsp</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why symbolic execution is the leading-edge method for generating test values</title>
      <dc:creator>Symflower</dc:creator>
      <pubDate>Sun, 20 Mar 2022 23:18:33 +0000</pubDate>
      <link>https://dev.to/symflower/why-symbolic-execution-is-the-leading-edge-method-for-generating-test-values-57kb</link>
      <guid>https://dev.to/symflower/why-symbolic-execution-is-the-leading-edge-method-for-generating-test-values-57kb</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yry-6oc0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xp41kiv41w7i3dz2vkd0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yry-6oc0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xp41kiv41w7i3dz2vkd0.png" alt="Image description" width="880" height="562"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/en/company/blog/2021/symbolic-execution/"&gt;first blog post&lt;/a&gt; of our blog series on &lt;strong&gt;Symflower's Core Technology&lt;/strong&gt;, we explained how symbolic execution works and &lt;strong&gt;how&lt;/strong&gt; we apply it to test source code, and generate unit tests. In this article, we will explain &lt;strong&gt;why&lt;/strong&gt; we decided to go with it, and why symbolic execution is superior to other methods that aim to generate test values.&lt;/p&gt;

&lt;h2&gt;
  
  
  Methods for automated test value generation
&lt;/h2&gt;

&lt;p&gt;When picking a technique to receive input values for different software tests, we can differentiate between &lt;a href="https://en.wikipedia.org/wiki/White-box_testing"&gt;white-box&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Black-box_testing"&gt;black-box testing&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;White-box testing&lt;/strong&gt; takes the source code into account and picks specific test values to trigger certain paths of code to verify their behavior. If the code is exhaustively analyzed, for instance, by a clever algorithm, one aims to choose the test inputs in a manner that triggers all possible execution paths in order to reveal all the unexpected and incorrect outcomes. Examples for white-box testing techniques include &lt;strong&gt;bounded model checking&lt;/strong&gt; and &lt;strong&gt;symbolic execution&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Black-box testing&lt;/strong&gt; checks the correctness of programs without looking into the code, which means that the project is not analyzed. Instead, many tests are executed with any possible values. There are different methods to decide values such as &lt;strong&gt;boundary-value analysis&lt;/strong&gt; and &lt;strong&gt;fuzzing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To learn more about software testing itself, check out our &lt;a href="https://dev.to/en/company/blog/2021/testing-part-1/"&gt;guide to software testing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the following sections, we discuss each method with examples, as well as how they work, and their limitations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Boundary-value analysis
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Boundary-value_analysis"&gt;Boundary-value analysis&lt;/a&gt; is commonly used by manual testers and thought for seminars on software test certifications. For generating test values with this method, the input value domains are partitioned. For instance, when testing a function that takes an integer as input, we could split the integer range every hundred steps into intervals from -100 to 0, 0 to 100, 100 to 200, and so on. Then, a minimum, maximum, and middle value are picked to test the code. Additionally, values just below and above the minimum and maximum are used. In our example, we could pick the values -1, 0, 1, 50, 99, 100, and 101 as inputs to test the function in the interval from 0 to 100. The idea behind this technique is to catch likely corner cases.&lt;/p&gt;

&lt;p&gt;The following example is a function that takes an integer array and an integer. If the given integer has the value 123, an index access is performed on the array. This access results in an index-out-of-range exception if the array does not contain an element at the desired position 456.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;foobar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;123&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;456&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The easiest way to trigger the exception is to call the function with an empty list, or just an undefined list (in Go this is &lt;code&gt;nil&lt;/code&gt; in Java it is &lt;code&gt;null&lt;/code&gt;) and the number 123 for &lt;code&gt;x&lt;/code&gt;. This is how such a test could look like, and is one of the tests Symflower generates for the given function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;tutorial&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;"testing"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;TestSymflowerFoobar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;123&lt;/span&gt;

  &lt;span class="n"&gt;foobar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, with boundary-value analysis, countless tests are performed, tests that are likely to still miss the index-out-of-range exception.&lt;/p&gt;

&lt;p&gt;Since the source code is not analyzed, possible misbehavior of a program such as the index-out-of-range exception in the example above is not specifically searched for, and is only revealed with pure luck. Therefore, this method can only achieve poor coverage in real-world source code. For example, the "if" branch of the function above is only covered by boundary-value analysis if we are lucky enough to pick exactly the right value for &lt;code&gt;x&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fuzzing
&lt;/h3&gt;

&lt;p&gt;With &lt;a href="https://en.wikipedia.org/wiki/Fuzzing"&gt;fuzzing&lt;/a&gt;, random values are produced automatically to test the code. The function under test is executed repeatedly with the generated input values in order to reveal problematic behavior, such as program failures.&lt;/p&gt;

&lt;p&gt;However, finding bugs like the index-out-of-range exception in the example above in a reasonable amount of time depends on how the fuzzer chooses the input values. How long does it take the generator to produce our malicious input 123? Has the random value generation stopped before that? If so, the fuzzer does not expose the bug. Covering the input domain is even trickier when dealing with more complex structures, as the possibilities for different inputs explode. See our &lt;a href="https://dev.to/en/company/blog/2022/go-beta-fuzzing-vs-symflower/"&gt;blog post about the Go fuzzer&lt;/a&gt; to view an analysis of a simple example about strings. Even though Go's native fuzzing is very powerful, the tool does not execute the desired string case of the example in the first 20 (!) minutes. Hence, similarly to boundary-value analysis, the reached coverage of fuzzing depends on luck, while wasting resources for an awful lot of unnecessary program executions.&lt;/p&gt;

&lt;p&gt;Additionally, the generated test values are not like a human would pick them. For instance, to reveal an error path that is guarded with the condition &lt;code&gt;x &amp;gt; 123&lt;/code&gt;, the assignment &lt;code&gt;x = 124&lt;/code&gt; in the corresponding test is much more intuitive than an arbitrary 32-bit integer greater than 123, let's say &lt;code&gt;x = 274032187&lt;/code&gt;. As a result, developers have a hard time understanding and using tests that contain these values for debugging found problems.&lt;/p&gt;

&lt;p&gt;Imagine a string structure "Color" that only allows the strings "red", "blue", "green" and "yellow", and the following piece of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;myColorInput&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"blue"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"sky"&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"green"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"grass"&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"yellow"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"sun"&lt;/span&gt;
&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"rainbow"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A fuzzer may provide a test that covers the default case, but since the underlying structure is not analyzed, the chance is virtually zero that a value "red" is generated. Consequently, it is not obvious from the produced random string values to the developer that they missed one case.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bounded model checking
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Model_checking"&gt;Bounded model checking&lt;/a&gt; is a technique that takes the given source code into account, and can therefore produce higher coverage. For analyzing programs, models of the given source code are specified as logic formulas that are checked for satisfiability. &lt;a href="https://dev.to/en/company/blog/2021/it-is-simply-math/"&gt;Read on&lt;/a&gt; to learn about satisfiability problems and how to solve them. For deeper insights into bounded model checking of finite program executions, we recommend &lt;a href="https://www.cs.cmu.edu/~emc/papers/Books%20and%20Edited%20Volumes/Bounded%20Model%20Checking.pdf"&gt;this article by Armin Biere et al.&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A clear disadvantage of bounded model checking, however, is that the analyses are limited in depth and complexity, e.g. bugs that occur only on deep levels of loops and recursions cannot be found in a scaling manner or even not at all.&lt;/p&gt;

&lt;p&gt;In the following example, the given function takes two integers and performs a number of loop iterations, which is determined by the input. If the loop is executed the right amount of times, the program fails with a division by zero. The bug may or may not be found, depending on the implementation of the bounded model checker.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="c"&gt;// This needs to be executed at least 10 times to reveal the error. Hence, "j" needs to be chosen to be a high enough number.&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;// The edge case "a == k" was overlooked in this condition.&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Here, the division by zero happens for "a == k".&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Symbolic execution
&lt;/h3&gt;

&lt;p&gt;With &lt;a href="https://en.wikipedia.org/wiki/Symbolic_execution"&gt;symbolic execution&lt;/a&gt;, the source code is executed with symbolic values instead of actual ones, meaning that the instances can be picked at the end of the analysis. Conditions on these symbolic values are collected along the way and expressed in mathematical language. Finally, values that fulfill these conditions are computed. In this way, symbolic execution is able to trigger all possible execution paths of the program with the produced input values. This technique is the premier class of program analysis since it is theoretically unlimited in depth and complexity. By utilizing symbolic execution, Symflower searches for all possible bugs in your software and supplies optimized unit tests that are easy to read and ideal for debugging. To see an example and learn more, read our &lt;a href="https://dev.to/en/company/blog/2021/symbolic-execution/"&gt;blog post about symbolic execution&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;Please note that black-box testing techniques can be helpful to check the behavior of your program. However, lots and lots of tests are generated unnecessarily, resulting in a waste of resources. And the main problem remains, as the same for bounded model checking: Not all computation paths are validated, and &lt;strong&gt;dangerous bugs stay hidden&lt;/strong&gt;. This is why Symflower decided to go with symbolic execution, the champion of program analysis.&lt;/p&gt;

&lt;p&gt;Naturally, there are also issues that are problematic for symbolic execution, such as path explosion or calls to the environment like programs that interact with files. Tackling these challenges is, however, worth it to be able to analyze arbitrary projects. Concluding, Symflower picks the best of the best methods, which is the only way of &lt;strong&gt;fully autonomously&lt;/strong&gt; assuring quality for all software there is.&lt;/p&gt;

&lt;p&gt;Stay tuned about &lt;strong&gt;Symflower's Core Technology&lt;/strong&gt; and upcoming blog posts of this series. Sign up for our newsletter and follow us on &lt;a href="https://twitter.com/symflower"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.facebook.com/symflower"&gt;Facebook&lt;/a&gt;, and &lt;a href="https://www.linkedin.com/company/symflower"&gt;LinkedIn&lt;/a&gt; for more content.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>devops</category>
    </item>
    <item>
      <title>How real-time autonomous unit testing can help you develop better software</title>
      <dc:creator>Symflower</dc:creator>
      <pubDate>Sun, 20 Mar 2022 23:13:38 +0000</pubDate>
      <link>https://dev.to/symflower/how-real-time-autonomous-unit-testing-can-help-you-develop-better-software-ca5</link>
      <guid>https://dev.to/symflower/how-real-time-autonomous-unit-testing-can-help-you-develop-better-software-ca5</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OATOnPJP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fy8zk9aodrddnvdqxr8s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OATOnPJP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fy8zk9aodrddnvdqxr8s.png" alt="Image description" width="880" height="562"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Having to deal with code quality issues deep in a project’s life-cycle is a shared nightmare between all developers.&lt;/strong&gt; There is nothing worse than being knee-deep in development – or, in a worst-case scenario, already in production – and realizing that the code you’re working with is full of holes that will impact the product’s success.&lt;/p&gt;

&lt;p&gt;When looking into catching code quality issues early on, unit testing is always an essential cornerstone. Through it, developers are capable of identifying issues and breaking points in your code in the early stages of development – however, unit tests are usually written and run after your code is already done, meaning you already lose time and effort on producing code that will most likely have to be corrected and changed due to human error either way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But what if we told you there was another way: to have your unit tests not only autonomously generated, but also being generated real-time while you’re working on your code, available at the end of your fingertips?&lt;/strong&gt; Let’s take a look at some of the benefits of a real-time, autonomous unit testing solution like &lt;a href="https://dev.to/en/products/symflower-cli"&gt;Symflower CLI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/369163972" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-time unit testing fits seamlessly into existing development processes
&lt;/h2&gt;

&lt;p&gt;Standard testing practices usually have a set order to them: you work on your code, test it, and then work on the issues. &lt;strong&gt;But why would you wait until your code is completely done and compiled to see whether it works?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of the biggest benefits of real-time autonomous unit testing is that &lt;strong&gt;it fits into your already existing development processes without you having to change anything.&lt;/strong&gt; There is no need to plan for writing tests, as they are automatically generated. There are no rounds of review needed to be scheduled after the fact, as the tests are generated on-the-go as you type.&lt;/p&gt;

&lt;p&gt;With your tests being instantly available as you work on your code, you’re able to introduce an additional layer of reactiveness and flexibility into your development processes that is not only agile at the core, but also helps you spend less time testing and debugging, reducing the overall work needed for a project to succeed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shift left with real-time feedback: faster iteration and error correction
&lt;/h2&gt;

&lt;p&gt;Time is always of the essence when it comes to development – you want to avoid having to go back to your code at a later time just to fix problems you could have during the early stages of development. &lt;strong&gt;What is better than being able to do so when the code is still fresh out of your mind, and you’re aware of all its little quirks?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Automated unit testing helps people generate and run in-depth tests for all kinds of use cases, and allows for longer and more complex tests that are sometimes avoided when it comes to manual testing, mainly due to them having to be constantly monitored. By default, automation already helps with filtering many of the human errors that can happen during manual testing, but when it comes to real-time feedback, it gets even better.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With a tool like &lt;a href="https://dev.to/en/products/symflower-cli"&gt;Symflower CLI&lt;/a&gt; generating unit tests for you right as you code, you’re not only able to identify the problems you’d eventually have to fix, but actually fix them right away as well.&lt;/strong&gt; This creates a workflow that is more efficient and fluid than having to go back and check things after the fact. Check out how it works here:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/673554843" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Better test coverage and efficiency, more specific results
&lt;/h2&gt;

&lt;p&gt;Automated tests are already a step up from simply doing manual testing: in fact, &lt;strong&gt;using automated testing alone has been proven to &lt;a href="https://collaboration.csc.ncsu.edu/laurie/Papers/Unit_testing_cameraReady.pdf"&gt;decrease defects in code by 20-30% and increase code quality in general&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Real-time autonomous unit testing, however, generates test cases based on the code that you’re writing as you’re writing it, which means it analyzes it bit-by-bit as it gets put down. This way of analyzing code and creating reactive test cases is able to provide for better code coverage with no dark spots, and more specific test results that can help you isolate problems easier and more granularly.&lt;/p&gt;

&lt;p&gt;This, combined with the &lt;a href="https://dev.to/en/features/symbolic-execution-rules/"&gt;symbolic execution&lt;/a&gt; test generation method used by Symflower CLI results in &lt;strong&gt;a solution that can not only cover relevant execution paths and problems through dedicated unit tests, but can also do so in a more reactive and efficient way than regular unit testing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you want to know more about why &lt;a href="https://dev.to/en/company/blog/2022/methods-for-automated-test-value-generation/"&gt;symbolic execution is the way to go over other test generation methods&lt;/a&gt;, check out our article on why we decided to go with it, and why we think you should give it a go, too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Saving time and money through failing fast
&lt;/h2&gt;

&lt;p&gt;When considering automated testing, "failing fast" is key: isolating and identifying problems within the code as soon as possible helps developers save time that would be spent on working on correcting them later on, and possibly reworking parts of the code that relied on the problematic ones.&lt;/p&gt;

&lt;p&gt;Real-time test generation takes "failing fast" to a new level, as detecting problems in the code happens instantly, and follows the code as it gets written. &lt;strong&gt;Finding these bugs at an earlier stage does not only save more development time than regular automated testing, but also lets developers save significant work hours, and focus on developing what’s really important: the product itself.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Having a better code quality and finding and iterating on problems faster is not only an advantage for developers, of course: through employing a real-time unit testing solution, companies can avoid the fallout that would result from a product of bad quality, as well as shorten their time to market significantly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Convinced that real-time, autonomous unit testing is the way to go? Check out &lt;a href="https://dev.to/en/products/symflower-cli"&gt;Symflower CLI&lt;/a&gt;, and get started today for free. For more content about software testing, sign up for our newsletter and follow us on &lt;a href="https://twitter.com/symflower"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.facebook.com/symflower"&gt;Facebook&lt;/a&gt;, and &lt;a href="https://www.linkedin.com/company/symflower"&gt;LinkedIn&lt;/a&gt;. See you next time!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>testing</category>
    </item>
    <item>
      <title>Better table-driven tests: generating Symflower-style unit tests</title>
      <dc:creator>Symflower</dc:creator>
      <pubDate>Sun, 20 Mar 2022 22:55:28 +0000</pubDate>
      <link>https://dev.to/symflower/better-table-driven-tests-generating-symflower-style-unit-tests-45o6</link>
      <guid>https://dev.to/symflower/better-table-driven-tests-generating-symflower-style-unit-tests-45o6</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VPRrIQhj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8qhy6s973ouoxfziqwxn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VPRrIQhj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8qhy6s973ouoxfziqwxn.png" alt="Better table-driven tests: generating Symflower-style unit tests" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ever wondered what the best style for writing unit tests is? We at Symflower have a certain take on that. We developed a test style optimized towards &lt;strong&gt;debuggability&lt;/strong&gt;, &lt;strong&gt;readability&lt;/strong&gt; and &lt;strong&gt;understandability&lt;/strong&gt;. This reduces the time spent on finding failing tests and understanding test cases, and therefore allows us to spend more time on actual development. We also created a &lt;a href="https://marketplace.visualstudio.com/items?itemName=symflower.symflower"&gt;Visual Studio Code extension&lt;/a&gt; to help us write those unit tests. Let's take a look at both of them!&lt;/p&gt;

&lt;h2&gt;
  
  
  Symflower-style table-driven unit tests
&lt;/h2&gt;

&lt;p&gt;In the beginning of Symflower, we were using the standard Go style for writing our table-driven tests. Over time we got increasingly unhappy with that style. The main reason was that it took some time and effort to figure out which test case was failing when we looked at the &lt;code&gt;go test&lt;/code&gt; output and its stack traces. We, therefore, developed our own style which solves this problem. By encapsulating the test cases in a call to a validation function, we were able to get meaningful stack traces for failing tests while still sticking to a table-driven style.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lMmUIfdy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t2imu9jenlzo2ezafpxf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lMmUIfdy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t2imu9jenlzo2ezafpxf.png" alt="Symflower-style table-driven unit tests" width="380" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Characteristics&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Table-driven&lt;/li&gt;
&lt;li&gt;Validation function&lt;/li&gt;
&lt;li&gt;Named test cases&lt;/li&gt;
&lt;li&gt;Structured test cases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Meaningful stack traces for failing tests&lt;/li&gt;
&lt;li&gt;Improved readability and understandability by named and structured test cases&lt;/li&gt;
&lt;li&gt;Reuse of validation code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The main purpose of our style is an improvement in debuggability and readability. Both aspects help us spend less time on debugging tests and stay focused on actual coding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Uw8uVW0A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tc96d5v30ce9zltjjip1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Uw8uVW0A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tc96d5v30ce9zltjjip1.png" alt="Stack traces for failing tests" width="180" height="53"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stack traces for failing tests.&lt;/strong&gt; This is probably the most important benefit of this style. Because of the calls to the validation function, each stack trace holds a location to the failing test case. In comparison, standard Go table-driven style can only have stack traces pointing to the validation, since the test cases do not forward their source code location.&lt;br&gt;
Developers often work around this problem by adding the name of the test cases to the assert messages, which can be can be skipped with the Symflower table-driven style as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hfp1VXIK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/58fireolwx9mbhwkgm3m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hfp1VXIK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/58fireolwx9mbhwkgm3m.png" alt="Named test cases" width="180" height="55"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Named test cases.&lt;/strong&gt; By adding human-readable text, the experience for the next person who is looking at the tests is improved. The named test cases also describe the behavior the test is supposed to check. This introduces a flavor of behavior-driven development to our unit tests.&lt;br&gt;
Another aspect of named tests is that they are easier to find if you are looking for a specific one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PDtInptc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7bqp1z1voc2nnhq3yk9h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PDtInptc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7bqp1z1voc2nnhq3yk9h.png" alt="Structured test cases" width="180" height="132"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structured test cases.&lt;/strong&gt; The test case definitions are split into name, input, and output by adding blank lines in between them. This way, it's always clear what the input and the expected output is. We do this regardless of whether there are multiple arguments or just a single one, it's a convention.&lt;br&gt;
Another important point is that we always make use of the field names in struct literals. Otherwise, it would become unreadable when several fields are involved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other test styles
&lt;/h2&gt;

&lt;p&gt;There are, of course, other frequently used test styles out there. We'll briefly showcase them for you, so that you have a proper base for comparison with the Symflower style.&lt;/p&gt;

&lt;h3&gt;
  
  
  Function per test case
&lt;/h3&gt;

&lt;p&gt;This is the most basic test style. Since every test case gets its own test function, there is a lot of redundant code, and the specific behavior a test case should check is also not described.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hcGNJ49f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2lf5ti1dpvljc708u0qv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hcGNJ49f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2lf5ti1dpvljc708u0qv.png" alt="Function per test case" width="380" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Redundant validation code&lt;/li&gt;
&lt;li&gt;Overview of existing tests is not great&lt;/li&gt;
&lt;li&gt;Long and hard to read test function names&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Standard Go style
&lt;/h3&gt;

&lt;p&gt;This is the style you see most often in Go projects. It's already table-driven, which is a huge improvement to the function-per-test-case style, since it reduces the amount of redundant code. However, there are still disadvantages, which are overcome by our style.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4R9_nTDX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mb0fzkoumrw0jphi5bia.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4R9_nTDX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mb0fzkoumrw0jphi5bia.png" alt="Standard Go style for table-driven unit test" width="300" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No relevant stack traces for failing tests&lt;/li&gt;
&lt;li&gt;No description of the behavior the test cases should check&lt;/li&gt;
&lt;li&gt;Missing field names make tests often hard to follow&lt;/li&gt;
&lt;li&gt;More fields and data make these tests often very hard to read and maintain&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Symflower VS Code Extension
&lt;/h2&gt;

&lt;p&gt;Creating unit tests will always involve writing some boiler-plate code. That's where editor extensions come in handy. &lt;a href="https://marketplace.visualstudio.com/items?itemName=symflower.symflower"&gt;The Symflower Visual Studio Code extension&lt;/a&gt; allows you to generate tests in the above unit test style, and even maintain them. Please drop us a line on our &lt;a href="https://github.com/symflower/symflower"&gt;public issue tracker&lt;/a&gt; if you are missing a feature, found a bug or just want to tell us how you like the extension and the unit test style.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--G2inG8t0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5tzif14s9qd0nupi5vvd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G2inG8t0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5tzif14s9qd0nupi5vvd.png" alt="The Symflower Visual Studio Code Extension" width="880" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our main area of expertise at Symflower is, however, &lt;a href="https://dev.to/en/products/symflower-cli/getting-started/"&gt;generating actual unit tests&lt;/a&gt;, and not just test skeletons. With this in mind, the next feature in our pipeline is going to be aimed at providing you with unit tests that are integrated in your existing test suite.&lt;br&gt;
Sign up for our newsletter and follow us on &lt;a href="https://twitter.com/symflower"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.facebook.com/symflower"&gt;Facebook&lt;/a&gt;, and &lt;a href="https://www.linkedin.com/company/symflower"&gt;LinkedIn&lt;/a&gt; to get notified about the upcoming releases and news about programming and tech.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>testing</category>
    </item>
    <item>
      <title>A COMPLETE guide on how to make Docker images even smaller</title>
      <dc:creator>Symflower</dc:creator>
      <pubDate>Wed, 16 Mar 2022 09:46:36 +0000</pubDate>
      <link>https://dev.to/symflower/a-complete-guide-on-how-to-make-docker-images-even-smaller-5dfn</link>
      <guid>https://dev.to/symflower/a-complete-guide-on-how-to-make-docker-images-even-smaller-5dfn</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v95Zhl0K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7fz51006m2ufnuarnb95.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v95Zhl0K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7fz51006m2ufnuarnb95.png" alt='"Small container images"' width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These days everything is either moving or already running in &lt;a href="https://www.docker.com/resources/what-container"&gt;containers&lt;/a&gt; when it comes to software infrastructure. &lt;strong&gt;The very first container of Symflower was not for our product&lt;/strong&gt;, some service or our website, it was our &lt;a href="https://en.wikipedia.org/wiki/Continuous_integration"&gt;continuous integration (CI)&lt;/a&gt;. Starting off with an almost tiny 100MB, we noticed that our baby Docker container image has grown to &lt;strong&gt;a full-size monster&lt;/strong&gt; with a whopping 6.2GB. Here is a step-by-step guide &lt;strong&gt;on how you can reduce the size of your container images&lt;/strong&gt; and how we slimmed down our oversized monster image.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{{&amp;lt; info-block &amp;gt;}}&lt;/code&gt;&lt;br&gt;
Please note that this article is not just a bunch of tips, but is really meant as a complete guide with debugging information on how to slim down your container images. While only Docker is mentioned, these steps and techniques are applicable to most solutions. In any case, if you find a step that we missed towards a smaller image size: tell us! We will extend the article so the next person benefits from your feedback.&lt;br&gt;
&lt;code&gt;{{&amp;lt;/ info-block &amp;gt;}}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{{&amp;lt; table-of-contents &amp;gt;}}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As with everything in the world of software development and infrastructure, we can rely on best practices that others have already established by most likely wading through hours of painful research.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;For a comprehensive guide to reducing the size of Docker images, continue reading on Symflower's blog:&lt;br&gt;
&lt;a href="https://symflower.com/en/company/blog/2022/complete-guide-on-shrinking-container-images/"&gt;A COMPLETE guide on how to make Docker images even smaller&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>docker</category>
      <category>tutorial</category>
      <category>devops</category>
    </item>
    <item>
      <title>Getting started with Visual Studio Code extension development</title>
      <dc:creator>Symflower</dc:creator>
      <pubDate>Wed, 16 Mar 2022 08:31:35 +0000</pubDate>
      <link>https://dev.to/symflower/getting-started-with-visual-studio-code-extension-development-56g2</link>
      <guid>https://dev.to/symflower/getting-started-with-visual-studio-code-extension-development-56g2</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr0ezz89mjd7ovkano1xt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr0ezz89mjd7ovkano1xt.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most developers have used Visual Studio Code at some point in their careers. It has been voted the most popular IDE of 2021 by respondents of the &lt;a href="https://insights.stackoverflow.com/survey/2021#most-popular-technologies-new-collab-tools" rel="noopener noreferrer"&gt;StackOverflow developer survey&lt;/a&gt;, and its appeal is clear as ever. While the base program provides a framework for an IDE, all of the language support and special features are delivered as extensions, which makes it easy to extend and customize your installation. So inevitably, there comes a point where you want to write your own extension. This guide will walk you through the basics of getting started with Visual Studio Code extension development.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a VS Code extension?
&lt;/h2&gt;

&lt;p&gt;Before we jump into coding, we should clear up what a VS Code extension is on a technical level. Extensions are basically programs, written in JavaScript or TypeScript, which hook into various parts of VS Code. They provide functions for VS Code to call when certain events happen, and can programmatically interact with (some parts of) VS Code in those functions.&lt;/p&gt;

&lt;p&gt;Extensions are distributed as ZIP files with a specific file and folder structure inside. The files contained in this structure are usually very verbose and not friendly for humans to read or write so there’s an official build tool to generate such ZIP files from source code: &lt;code&gt;vsce&lt;/code&gt;. Its usage will be explained later on in this post.&lt;/p&gt;

&lt;p&gt;Development is best done in VS Code itself. It supports TypeScript out of the box and comes with special tools to run and debug your extension in another instance. In principle, other editors would work as well, but you should have VS Code ready for running and testing your extension either way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started with VS Code extensions
&lt;/h2&gt;

&lt;p&gt;For starters, let’s install some command-line tools for development:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--global&lt;/span&gt; yo generator-code vsce


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;…and set up our project.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ yo code

     _-----_     ╭──────────────────────────╮
    |       |    │   Welcome to the Visual  │
    |--(o)--|    │   Studio Code Extension  │
   `---------´   │        generator!        │
    ( _´U`_ )    ╰──────────────────────────╯
    /___A___\   /
     |  ~  |
   __'.___.'__
 ´   `  |° ´ Y `

? What type of extension do you want to create? New Extension (TypeScript)
? What's the name of your extension? hello-world
? What's the identifier of your extension? hello-world
? What's the description of your extension?
? Initialize a git repository? Yes
? Bundle the source code with webpack? No
? Which package manager to use? npm

Writing in /src/hello-world...
[...]


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Choose “New Extension (TypeScript)” and enter your extension’s details. You can always change these settings later. Optionally, initialize a Git repository and accept the default of “No” for “Bundle the source code with webpack?”. Select the package manager on your system (most likely “npm”). After that, open the newly created folder in your editor of choice and open &lt;code&gt;src/extension.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is the entry point of your extension. VS Code will evaluate this file when loading your extension — but make sure you don’t put your initialization code directly in the top-level scope of the script!&lt;/p&gt;

&lt;p&gt;A special function called &lt;code&gt;activate&lt;/code&gt; is intended for setup code, and is called by VS Code when an extension is first “needed” after being deactivated, freshly installed, or after VS Code was started. “Needed” in this case means that one of several &lt;a href="https://code.visualstudio.com/api/references/activation-events" rel="noopener noreferrer"&gt;Activation Events&lt;/a&gt; has been triggered. The generated example code demonstrates this with a command Activation Event, but we’ll also explore another way to start your extension later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running a VS Code extension in development mode
&lt;/h2&gt;

&lt;p&gt;Let’s have a look at the generated demo code in action! As mentioned before, it registers a command which can be run in the command launcher (Ctrl+Shift+P by default), so let’s try that now.&lt;/p&gt;

&lt;p&gt;If you’re already in VS Code, go to the “Run &amp;amp; Debug” tab in the leftmost sidebar. Select the “Run Extension” launch configuration in the dropdown next to the green “Run” button. Then press the “Run” button (or F5).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ru7s5q09xf7ifvvxszw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ru7s5q09xf7ifvvxszw.png" alt=""&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;If you’re not working from VS Code, run&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

code &lt;span class="nt"&gt;--extensionDevelopmentPath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;…from your shell. Note that the path given to &lt;code&gt;--extensionDevelopmentPath&lt;/code&gt; has to be absolute.&lt;/p&gt;

&lt;p&gt;VS Code will open, either with no workspace folder at all or with a recently opened workspace. Next, just press Ctrl+Shift+P and type “hello world”. A new command called “Hello World” should show up. Select it, hit Enter and a notification should appear.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F21xapfe2i1ixwm7ke8ai.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F21xapfe2i1ixwm7ke8ai.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Checking back with the code, we can clearly see how this is implemented. The call to &lt;code&gt;registerCommand&lt;/code&gt; tells VS Code what to do when the “Hello World” command is executed. However, this just provides the implementation. The definition of our command lives in the &lt;code&gt;package.json&lt;/code&gt; file, under the &lt;code&gt;contributes&lt;/code&gt; section.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"contributes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"commands"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hello-world.helloWorld"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello World"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;A lot of extension functionality is defined in &lt;code&gt;contributes&lt;/code&gt;: language support, settings, commands &lt;a href="https://code.visualstudio.com/api/references/contribution-points" rel="noopener noreferrer"&gt;and more&lt;/a&gt;. These definitions are referred to as “Contribution Points”.&lt;/p&gt;

&lt;p&gt;Back in &lt;code&gt;extension.ts&lt;/code&gt;, we can see that the return value from &lt;code&gt;registerCommand&lt;/code&gt; is pushed onto &lt;code&gt;context.subscriptions&lt;/code&gt;. What’s that all about?&lt;br&gt;
“Subscriptions” might be a bit misleading here. More commonly, VS Code uses the term “Disposable”. Let’s check &lt;a href="https://code.visualstudio.com/api/references/vscode-api#Disposable" rel="noopener noreferrer"&gt;the docs&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Represents a type which can release resources, such as event listening or a timer.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Okay cool. TL;DR: most of the time, Disposables represent something that can be “stopped” or canceled (for example, providing a function to call when a command is invoked, as shown in the demo code). When your extension deactivates, &lt;code&gt;context.subscriptions&lt;/code&gt; calls &lt;code&gt;dispose&lt;/code&gt; on the Disposables pushed onto it, which makes it a handy tool for managing lifetime-scoped Disposables (like command handlers).&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploring the VS Code extension API
&lt;/h2&gt;

&lt;p&gt;Time to add some features. Let’s display a notification when a file is saved. It’s pretty simple: We just have to register an event listener. Since the event is related to workspaces (think editors and files), we find its handle in &lt;code&gt;vscode.workspaces&lt;/code&gt;. &lt;code&gt;onDidSaveTextDocument&lt;/code&gt; seems appropriate, so let’s just call it from inside the &lt;code&gt;activate&lt;/code&gt; function:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;disposable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onDidSaveTextDocument&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;showInformationMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Saved &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscriptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;disposable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Since the event listener — much like a command handler — is a “continuous thing” that can be “stopped” the registration function returns a Disposable which we have to handle. Pushing it into &lt;code&gt;context.subscriptions&lt;/code&gt; is a good fit here since we never want to stop listening for save events while our extension is active.&lt;/p&gt;

&lt;p&gt;Alright, let’s run that. Just press F5 to launch the last configuration again, open a text document, save and… oh no. Nothing’s happening! The problem is an easy one: our extension has not been activated yet. Remember Activation Events? As mentioned before, our extension is currently only command-activated. If you run the “Hello World” command, then try saving again, a notification should appear as expected.&lt;/p&gt;

&lt;p&gt;We can see the configuration responsible for that in the &lt;code&gt;package.json&lt;/code&gt; file under &lt;code&gt;activationEvents&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"activationEvents"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"onCommand:hello-world.helloWorld"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Currently, only one Activation Event is registered called &lt;code&gt;onCommand:hello-world.helloWorld&lt;/code&gt;. This event fires when the “Hello World” command is executed. Since we would like to listen to all file save events without first having to run a command, let’s replace the whole &lt;code&gt;onCommand[…]&lt;/code&gt; string with &lt;code&gt;onStartupFinished&lt;/code&gt;, which fires right after VS Code has started.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"activationEvents"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"onStartupFinished"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In general, you should aim for more specific Activation Events. Less extensions to start at once makes VS Code start up faster.&lt;/p&gt;

&lt;p&gt;Now, let’s restart our launch configuration, open a file in the development host and save. Our extension finally displays a notification! By the way, if you leave the “Extension Development” instance of VS Code open while making changes, you can also press Ctrl+R to reload the window and try your changes instantly.&lt;/p&gt;

&lt;p&gt;Let’s add a status bar item. TL;DRtD (too long, didn’t read the docs) this is the code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;disposable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setStatusBarMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Never saved anything&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscriptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;disposable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;disposable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onDidSaveTextDocument&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;disposable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setStatusBarMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Saved &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; at &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscriptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;disposable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscriptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;disposable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Just replace what we added for &lt;code&gt;onDidSaveTextDocument&lt;/code&gt; before.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbt8g0kh267b9fu55vwl3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbt8g0kh267b9fu55vwl3.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The status bar is part of the window, so we find its functionality in &lt;code&gt;vscode.window&lt;/code&gt;. Makes sense! Status bar items are Disposables. Why? If you think about it: Status bar items can disappear, so it makes sense to use the Disposable interface here. We’ll just handle them via &lt;code&gt;context.subscriptions&lt;/code&gt; again.&lt;/p&gt;

&lt;p&gt;One thing to note from &lt;a href="https://code.visualstudio.com/api/references/vscode-api#window.setStatusBarMessage" rel="noopener noreferrer"&gt;the docs&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that status bar messages stack and that they must be disposed when no longer used.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;They &lt;em&gt;stack?&lt;/em&gt; Well, if we add a timeout to the “saved” status bar messages only, we can see this in action. Just pass a number as the second parameter to the call.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setStatusBarMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Saved &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; at &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;“Saved” messages will disappear after one second to reveal the message below (down to “Never saved anything”). This function pushes status bar messages onto a stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building and installing a VS Code extension
&lt;/h2&gt;

&lt;p&gt;Okay, that was enough about development workflows and general concepts. Let’s finally build that special ZIP file mentioned in the beginning so you can actually install and use your extension. Open your extension’s source directory in a terminal and run &lt;code&gt;vsce package&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

vsce package
Executing prepublish script &lt;span class="s1"&gt;'npm run vscode:prepublish'&lt;/span&gt;...

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; hello-world@0.0.1 vscode:prepublish /src/hello-world
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; npm run compile


&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; hello-world@0.0.1 compile /src/hello-world
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; tsc &lt;span class="nt"&gt;-p&lt;/span&gt; ./

ERROR  Make sure to edit the README.md file before you package or publish your extension.


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;…&lt;/p&gt;

&lt;p&gt;Okay, apparently &lt;code&gt;vsce&lt;/code&gt; thinks we intended to publish the extension and forgot to change the default generated README. Thanks. I like to resolve this situation with a quick &lt;code&gt;echo this is not useful &amp;gt; README.md&lt;/code&gt; but you’re welcome to write a more useful README.&lt;/p&gt;

&lt;p&gt;After this, we just re-run &lt;code&gt;vsce package&lt;/code&gt;. This command will also display some actually helpful warnings (which you can just ignore and continue anyways). Afterwards, you get a &lt;code&gt;*.vsix&lt;/code&gt; file. That’s the special ZIP file we mentioned, which you can open with a ZIP archive browser to explore its contents.&lt;/p&gt;

&lt;p&gt;Installing it into your main copy of VS Code is also pretty easy: On the command line, run &lt;code&gt;code --install-extension ./hello-world-0.0.1.vsix&lt;/code&gt;. In the GUI, go to “Extensions” and click the three horizontal dots at the top of the left sidebar. Click “Install from VSIX…” and select your VSIX file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyvxlk26vovoaai8u8hm3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyvxlk26vovoaai8u8hm3.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that’s it! You’re now a Visual Studio Code extension author. For more in-depth information about developing extensions and API references, check out the &lt;a href="https://code.visualstudio.com/api" rel="noopener noreferrer"&gt;official docs&lt;/a&gt;. For more VS Code guides from us, subscribe to our newsletter, and follow us on &lt;a href="https://twitter.com/symflower" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.facebook.com/symflower" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;, and &lt;a href="https://www.linkedin.com/company/symflower/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;. In the next blog posts we talk about publishing on the Marketplace, testing and our own super-advanced testing tools for VS Code extensions. Stay tuned!&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
