<?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: Daniel Kraus</title>
    <description>The latest articles on DEV Community by Daniel Kraus (@beatngu1101).</description>
    <link>https://dev.to/beatngu1101</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%2F29207%2F462432e4-f996-4744-9b52-39de22f31677.jpg</url>
      <title>DEV Community: Daniel Kraus</title>
      <link>https://dev.to/beatngu1101</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/beatngu1101"/>
    <language>en</language>
    <item>
      <title>Pre-push Commit Message Validation on Github (Enterprise)</title>
      <dc:creator>Daniel Kraus</dc:creator>
      <pubDate>Sat, 31 Aug 2024 15:33:05 +0000</pubDate>
      <link>https://dev.to/beatngu1101/pre-push-commit-message-validation-on-github-enterprise-25o0</link>
      <guid>https://dev.to/beatngu1101/pre-push-commit-message-validation-on-github-enterprise-25o0</guid>
      <description>&lt;p&gt;If you are looking for commit message validation on &lt;a href="https://github.com/marketplace?query=commit+message" rel="noopener noreferrer"&gt;GitHub's Marketplace&lt;/a&gt; (or other places on the Internet), e.g., to enforce &lt;a href="https://conventionalcommits.org/en/v1.0.0/" rel="noopener noreferrer"&gt;conventional commits&lt;/a&gt;, most solutions are based on GitHub Actions such as &lt;a href="https://github.com/GsActions/commit-message-checker" rel="noopener noreferrer"&gt;&lt;code&gt;GsActions/commit-message-checker&lt;/code&gt;&lt;/a&gt;. While this does the job, I believe using GitHub Actions for commit message validation has two downsides:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Since validation happens as part of a workflow, it consumes runner minutes.&lt;/li&gt;
&lt;li&gt;And because it is a workflow, the check happens &lt;em&gt;post&lt;/em&gt;-push (from a Git server perspective).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you are using GitHub Enterprise (Cloud, GHEC or Server, GHES), there is actually a GitHub-native solution: &lt;a href="https://docs.github.com/en/enterprise-cloud@latest/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/available-rules-for-rulesets#metadata-restrictions" rel="noopener noreferrer"&gt;metadata restrictions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Metadata restricions can be part of a branch or tag ruleset. That is, such a ruleset can be defined on the &lt;a href="https://docs.github.com/en/enterprise-cloud@latest/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets" rel="noopener noreferrer"&gt;repository&lt;/a&gt; or &lt;a href="https://docs.github.com/en/enterprise-cloud@latest/organizations/managing-organization-settings/managing-rulesets-for-repositories-in-your-organization" rel="noopener noreferrer"&gt;organization&lt;/a&gt; level. In the latter case, you can also use &lt;a href="https://docs.github.com/en/enterprise-cloud@latest/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization" rel="noopener noreferrer"&gt;custom properties&lt;/a&gt; to only target a subset of repositories (e.g., those of a specific team).&lt;/p&gt;

&lt;p&gt;In any case, when you create the ruleset, you have to scroll to the bottom of the page to "Restrictions" and check "Restrict commit metadata", where it says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Restrict commit author email addresses, committer email addresses, commit message content, and other metadata&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then click on "Add restriction", which opens the following dialog:&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%2Fzdwfyku2796ggx35m4o1.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%2Fzdwfyku2796ggx35m4o1.png" alt="GitHub metadata restriction dialog"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For "Requirement", you can choose among the following options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Must start with a matching pattern&lt;/li&gt;
&lt;li&gt;Must end with a matching pattern&lt;/li&gt;
&lt;li&gt;Must contain a matching pattern&lt;/li&gt;
&lt;li&gt;Must match a given regex pattern&lt;/li&gt;
&lt;li&gt;Must not start with a matching pattern (negation of 1.)&lt;/li&gt;
&lt;li&gt;Must not end with a matching pattern (negation of 2.)&lt;/li&gt;
&lt;li&gt;Must not contain a matching pattern (negation of 3.)&lt;/li&gt;
&lt;li&gt;Must not match a given regex pattern (negation of 4.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Afterwards, click "Add" and activate (or &lt;a href="https://docs.github.com/en/enterprise-cloud@latest/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/about-rulesets#using-ruleset-enforcement-statuses" rel="noopener noreferrer"&gt;evaluate&lt;/a&gt;) the ruleset – that's it!&lt;/p&gt;

&lt;p&gt;I think this a great way to validate commit messages &lt;em&gt;pre&lt;/em&gt;-push, GitHub-natively, without consuming runner minutes. And hopefully, this will someday also be part of GitHub's free tier. 🤞&lt;/p&gt;

</description>
      <category>github</category>
      <category>githubenterprise</category>
      <category>git</category>
    </item>
    <item>
      <title>Handling System Properties in JUnit 5</title>
      <dc:creator>Daniel Kraus</dc:creator>
      <pubDate>Wed, 08 Jan 2020 11:30:02 +0000</pubDate>
      <link>https://dev.to/beatngu1101/handling-system-properties-in-junit-5-4iom</link>
      <guid>https://dev.to/beatngu1101/handling-system-properties-in-junit-5-4iom</guid>
      <description>&lt;p&gt;In Java, &lt;a href="https://docs.oracle.com/javase/tutorial/essential/environment/properties.html"&gt;properties&lt;/a&gt; are configuration values that are represented as key-value pairs, usually managed inside a &lt;code&gt;Properties&lt;/code&gt; object. &lt;a href="https://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html"&gt;System properties&lt;/a&gt; are basically the &lt;code&gt;Properties&lt;/code&gt; object of the &lt;code&gt;System&lt;/code&gt; class, which "describes the configuration of the current working environment". This includes information about the current user, the OS or the Java runtime. The &lt;code&gt;System&lt;/code&gt; class offers various methods to interact with its properties, however, the ones most used are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;clearProperty(String key)&lt;/code&gt;: Removes the system property indicated by the specified key.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getProperty(String key)&lt;/code&gt;: Gets the system property indicated by the specified key.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setProperty(String key, String value)&lt;/code&gt;: Sets the system property indicated by the specified key.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes you need to control system properties when you test code that somehow uses &lt;code&gt;System&lt;/code&gt;. When doing so, you shouldn't just wildly mutate their values, otherwise tests might inadvertently depend on possible side effects. Then, changes in your test code, or even changing the execution order, may lead to test failures that are hard to debug. Therefore, you want to have a proper restore mechanism in place that cleans up the environment after each test.&lt;/p&gt;

&lt;p&gt;When it comes to &lt;a href="https://junit.org/junit4/"&gt;JUnit 4&lt;/a&gt;, there are already off-the-shelf libraries for this such as the fantastic &lt;a href="https://stefanbirkner.github.io/system-rules/"&gt;System Rules&lt;/a&gt; project. But for &lt;a href="https://junit.org/junit5/"&gt;JUnit 5&lt;/a&gt;, you had to come up with a custom solution—at least until now.&lt;/p&gt;

&lt;p&gt;There is &lt;a href="https://junit-pioneer.org/"&gt;JUnit Pioneer&lt;/a&gt;, a semi-official extension pack for JUnit 5. It offers various neat extensions, and as of version 0.5.0 also a mechanism to handle system properties in a safe manner. The &lt;code&gt;@ClearSystemProperty&lt;/code&gt; and &lt;code&gt;@SetSystemProperty&lt;/code&gt; annotation respectively, can be used to clear and set the values of system properties for a test execution. Both annotations work on the test method and class level, are repeatable as well as combinable. After the annotated method has been executed, the properties mentioned in the annotation will be restored to their original value or will be cleared if they didn't have one before. Other system properties that are changed during the test, are &lt;em&gt;not&lt;/em&gt; restored.&lt;/p&gt;

&lt;p&gt;For example, clearing a system property for a test execution can be done as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="nd"&gt;@ClearSystemProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"some property"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;assertNull&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;getProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"some property"&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;And setting a system property for a test execution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="nd"&gt;@SetSystemProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"some property"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"new value"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"new value"&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;getProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"some property"&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 mentioned before, both annotations are repeatable and they can also be combined:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="nd"&gt;@ClearSystemProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1st property"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@ClearSystemProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2nd property"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@SetSystemProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"3rd property"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"new value"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;assertNull&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;getProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1st property"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;assertNull&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;getProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2nd property"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"new value"&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;getProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"3rd property"&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;Note that class level configurations are overwritten by method level configurations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@ClearSystemProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"some property"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MySystemPropertyTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="nd"&gt;@SetSystemProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"some property"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"new value"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"new value"&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;getProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"some property"&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;Sometimes, you might also need to set a system property to a value that is not a constant expression, which is required for annotation values. In this case, you can still leverage the restore mechanism:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@ParameterizedTest&lt;/span&gt;
&lt;span class="nd"&gt;@ValueSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"bar"&lt;/span&gt; &lt;span class="o"&gt;})&lt;/span&gt;
&lt;span class="nd"&gt;@ClearSystemProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"some property"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;test&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;value&lt;/span&gt;&lt;span class="o"&gt;)&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;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"some property"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&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 you can see, both annotations are quite powerful and applicable in many situations. So, &lt;a href="https://github.com/junit-pioneer/junit-pioneer"&gt;become a JUnit Pioneer stargazer on GitHub&lt;/a&gt; and take back control of your system properties!&lt;/p&gt;

</description>
      <category>java</category>
      <category>junit</category>
      <category>junit5</category>
      <category>testing</category>
    </item>
    <item>
      <title>A Recipe for Successful Exploratory Testing</title>
      <dc:creator>Daniel Kraus</dc:creator>
      <pubDate>Tue, 13 Nov 2018 15:11:07 +0000</pubDate>
      <link>https://dev.to/beatngu1101/a-recipe-for-succesful-exploratory-testing-b1a</link>
      <guid>https://dev.to/beatngu1101/a-recipe-for-succesful-exploratory-testing-b1a</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://medium.com/@beatngu13/a-recipe-for-succesful-exploratory-testing-231dc8c44eea" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In today’s agile and automated realm of software development, I often hear people ask: What actually is the role of manual testing? Assume you live in a perfect world where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You always do test-driven development (TDD)&lt;/li&gt;
&lt;li&gt;All your tests are automated&lt;/li&gt;
&lt;li&gt;These tests produce 100% code coverage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do you still need manual testing? Well, let’s first reflect the three points from above. TDD typically means that both production and test code get written by the same developer. In addition, these tests always test the same path. As a consequence, you need a lot of them; not just to achieve your 100% code coverage, but also to cover the &lt;a href="https://automationintesting.com/2018/06/what-do-you-mean-by-ui-tests.html" rel="noopener noreferrer"&gt;risks&lt;/a&gt; of the system under test (SUT). And: automated tests are expensive. Not just in terms of maintenance, but also their creation — especially the higher you are in the &lt;a href="https://martinfowler.com/bliki/TestPyramid.html" rel="noopener noreferrer"&gt;test pyramid&lt;/a&gt;. Finally, many people within the testing community say that automated tests don’t do testing; they do &lt;a href="https://satisfice.com/blog/archives/856/" rel="noopener noreferrer"&gt;checking&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Testing&lt;/strong&gt; is the process of evaluating a product by learning about it through exploration and experimentation, which includes to some degree: questioning, study, modeling, observation, inference, etc.&lt;/p&gt;

&lt;p&gt;(A &lt;strong&gt;test&lt;/strong&gt; is an instance of testing.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Checking&lt;/strong&gt; is the process of making evaluations by applying algorithmic decision rules to specific observations of a product.&lt;/p&gt;

&lt;p&gt;(A &lt;strong&gt;check&lt;/strong&gt; is an instance of checking.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Especially now, with AI-based testing tools emerging both in academia and industry, this is a pretty interesting topic. We can easily let machines perform automated checking, but automated testing is still an open research question.&lt;/p&gt;

&lt;p&gt;I think a solid QA needs both. That is, smart automated checking but smarter manual testing. Automate the simple things to reveal trivial bugs and implement “[…] cleverly designed checks that monitor systems for important disturbances.” (&lt;a href="https://twitter.com/jamesmarcusbach/status/1051546045279293442/" rel="noopener noreferrer"&gt;Deep checking&lt;/a&gt;.) With regards to manual testing, not just do those tests that are too expensive to automate, explore and exploit the SUT constantly. This is where &lt;em&gt;exploratory testing&lt;/em&gt; comes in. In &lt;a href="https://satisfice.com/articles/et-article.pdf" rel="noopener noreferrer"&gt;“Exploratory Testing Explained”&lt;/a&gt;, James Bach defines it as “simultaneous learning, test design and test execution” and describes it as follows:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[…] any testing to the extent that the tester actively controls the design of the tests as those tests are performed and uses information gained while testing to design new and better tests.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doesn’t this sound good? Indeed, but without some guidance, exploratory testing can be a mess. Let me show you three basic ingredients, which I think make a successful recipe for exploratory testing.&lt;/p&gt;

&lt;h1&gt;
  
  
  1st Ingredient: Timebox ⏰
&lt;/h1&gt;

&lt;p&gt;The timebox defines the amount of time available for exploratory testing, which is usually between 30 – 60 minutes. Within this time frame, people are extremely focused, which increases the chance of finding bugs. Moreover, it makes planning possible; a team can decide per sprint, week, or day, on how much time they want to spend on exploratory testing. This way, also others (e.g. developers or domain experts) can easily incorporate some testing in their daily routines.&lt;/p&gt;

&lt;h1&gt;
  
  
  2nd Ingredient: Testing Tour 🗺
&lt;/h1&gt;

&lt;p&gt;The concept of testing tours has been around for a while. According to Michael Bolton’s blog post &lt;a href="http://developsense.com/blog/2009/04/of-testing-tours-and-dashboards/" rel="noopener noreferrer"&gt;“Of Testing Tours and Dashboards”&lt;/a&gt;, the history of “touring” goes back to the mid 90’s and became more and more popular around 2005. The idea: if, for example, a tourist finds himself in a new city, he usually explores it on the basis of various topics that personally interest him, such as museums, shopping facilities, bars, etc. The very same concept can be applied to exploratory testing: instead of having no focus and no control during testing, one can specify topics around which the SUT can explored. Here are some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Antisocial 🚷: always do the opposite&lt;/li&gt;
&lt;li&gt;Garbage collector 🗑: go street by street, house by house&lt;/li&gt;
&lt;li&gt;Landmark 🗽: most important features in different orders&lt;/li&gt;
&lt;li&gt;Supermodel 💃: GUI only&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Testing tours help to structure and organize exploratory testing so that, e.g., people don’t test the same feature over and over again, while other parts of the SUT aren’t tested at all. Using distinct and catchy names like the ones above, tours quickly become part of the team’s vocabulary and can also help new team members get used to the SUT.&lt;/p&gt;

&lt;h1&gt;
  
  
  3rd Ingredient: Protocol 📓
&lt;/h1&gt;

&lt;p&gt;Protocols are usually quite unpopular; they require unpleasant writing effort and often they are read by no one. But: when it comes to exploratory testing, protocols can be a powerful tool. First of all, they simply record what has been tested. This allows to go back in time and see why a particular bug hasn’t been found. It also gives the opportunity to see what worked in the past and what didn’t. Furthermore, if a test case has proven itself to be very effective, the corresponding protocol(s) can be used as a blueprint for automating it. Let’s have a look at an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 2018-11-02T09:30

Scope: my software
Tour: landmark
Timebox: 30 minutes
Legend: (C)orrect, (B)ug, (?) unknown

# Test Cases

## 1

1) open menu "x" via "y" - C
2) select "z" and type in "foo" - C
3) fill out form bottom to top - B

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

&lt;/div&gt;



&lt;p&gt;This protocol uses &lt;a href="https://en.wikipedia.org/wiki/Markdown" rel="noopener noreferrer"&gt;Markdown&lt;/a&gt; for formatting, which can be utilized to extract other formats such as HTML or PDF (e.g. with &lt;a href="https://pandoc.org/" rel="noopener noreferrer"&gt;Pandoc&lt;/a&gt;). The protocol itself should be lightweight and informal. This encourages people to write &lt;em&gt;and&lt;/em&gt; read it. Plus: a protocol like this can also help new team members to get on board easier.&lt;/p&gt;




&lt;p&gt;Note that these are just loose guidelines. Some teams like to use Git-versioned Markdown files for their protocols, whereas others may prefer Excel sheets in a private cloud. Feel free to customize the entire process to your team’s/department’s/organization’s individual needs, but without disregarding the basic concepts.&lt;/p&gt;

&lt;p&gt;In that sense, bon appétit!&lt;/p&gt;

&lt;p&gt;Further reading:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://amazon.de/dp/0321636414/" rel="noopener noreferrer"&gt;James A. Whittaker: Exploratory Software Testing: Tips, Tricks, Tours, and Techniques to Guide Test Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amazon.de/dp/0471358460/" rel="noopener noreferrer"&gt;Cem Kaner, Jack Falk, Hung Q. Nguyen: Testing Computer Software&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amazon.de/dp/0471081124/" rel="noopener noreferrer"&gt;Cem Kaner, James Bach, Bret Pettichord: Lessons Learned in Software Testing: A Context-Driven Approach&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>exploratorytesting</category>
      <category>testing</category>
      <category>qa</category>
      <category>codequality</category>
    </item>
    <item>
      <title>What Are Your Top Three Conference Talks?</title>
      <dc:creator>Daniel Kraus</dc:creator>
      <pubDate>Sun, 20 Aug 2017 12:26:15 +0000</pubDate>
      <link>https://dev.to/beatngu1101/what-are-your-top-three-conference-talks</link>
      <guid>https://dev.to/beatngu1101/what-are-your-top-three-conference-talks</guid>
      <description>&lt;p&gt;I start off with these masterpieces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://youtu.be/0SARbwvhupQ"&gt;Brian Fitzpatrick and Ben Collins-Sussman (Google I/O 2009): The Myth of the "Genius Programmer"&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtu.be/8pTEmbeENF4"&gt;Bret Victor (DBX 2013): The Future of Programming&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.infoq.com/presentations/Simple-Made-Easy"&gt;Rich Hickey (Strange Loop 2011): Simple Made Easy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What are yours?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>learning</category>
      <category>conferences</category>
      <category>talks</category>
    </item>
    <item>
      <title>A Formal Look at Selenium’s NoSuchElementException</title>
      <dc:creator>Daniel Kraus</dc:creator>
      <pubDate>Sat, 12 Aug 2017 21:20:48 +0000</pubDate>
      <link>https://dev.to/beatngu1101/a-formal-look-at-seleniums-nosuchelementexception</link>
      <guid>https://dev.to/beatngu1101/a-formal-look-at-seleniums-nosuchelementexception</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://medium.com/@beatngu13/a-formal-look-at-seleniums-nosuchelementexception-bafce97df2e7" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As a Selenium user, you probably know the story: Out of a sudden, your tests fail due to the infamous &lt;code&gt;NoSuchElementException&lt;/code&gt;. But this isn't something that only happens with Selenium. Most other test automation frameworks have their own (fancy) names for it, but the underlying problem is always the same: a particular UI element cannot be found.&lt;/p&gt;

&lt;p&gt;Back in 2016, I did a small review on several Swing-compatible capture &amp;amp; replay tools as part of a project work at my alma mater. During this work, I stumbled across &lt;a href="http://www.cs.umd.edu/~atif/pubs/McMasterMemonTESTBEDS2009.pdf" rel="noopener noreferrer"&gt;“An Extensible Heuristic-Based Framework for GUI Test Case Maintenance”&lt;/a&gt; by Scott McMaster and Atif M. Memon. In this paper, the authors introduced a formal model for the described situation—the &lt;em&gt;GUI element identification problem&lt;/em&gt;. The problem typically occurs in regression testing, hence, between version &lt;em&gt;n&lt;/em&gt; and &lt;em&gt;n&lt;/em&gt; + &lt;em&gt;i&lt;/em&gt; of the system under test (SUT). (Note that these versions are not necessarily stable releases, every change that is built can cause the phenomenon.) Since McMaster and Memon seemed to focus on desktop applications, it affected the terminology they have chosen. For instance, a separate window within the SUT is denoted as set &lt;em&gt;W&lt;/em&gt;, containing various actionable GUI elements &lt;em&gt;e&lt;/em&gt;. If you come from a web application background, you would probably speak of pages and UI elements. Sometimes, you also want to assert or verify non-actionable elements such as labels to ensure they contain a certain string. Nonetheless, the concept is essentially the same. &lt;em&gt;W&lt;/em&gt;’ is a subsequent version of &lt;em&gt;W&lt;/em&gt;, in which the number of elements &lt;em&gt;e&lt;/em&gt;’ might vary (i.e. |&lt;em&gt;W&lt;/em&gt;| ≠ |&lt;em&gt;W&lt;/em&gt;’|, if you are unfamiliar with this notation, have a look at these quick references on &lt;a href="http://www.rapidtables.com/math/symbols/Logic_Symbols.htm" rel="noopener noreferrer"&gt;logic&lt;/a&gt; and &lt;a href="http://www.rapidtables.com/math/symbols/Set_Symbols.htm" rel="noopener noreferrer"&gt;set theory&lt;/a&gt;). Now, the GUI element identification problem is defined as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For each actionable GUI element &lt;em&gt;e&lt;/em&gt; in &lt;em&gt;W&lt;/em&gt;, find a corresponding (possibly modified) element &lt;em&gt;e&lt;/em&gt;’ in &lt;em&gt;W&lt;/em&gt;’ whose actions implement the same functionality.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In order to do so, each element &lt;em&gt;e&lt;/em&gt;, &lt;em&gt;e&lt;/em&gt;’ ∈ &lt;em&gt;W&lt;/em&gt; ∪ &lt;em&gt;W&lt;/em&gt;’ must be assigned to exactly one of the following three sets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deleted:&lt;/strong&gt; elements from &lt;em&gt;W&lt;/em&gt; with no corresponding elements in &lt;em&gt;W&lt;/em&gt;’, therefore, they have been deleted in version &lt;em&gt;n&lt;/em&gt; + &lt;em&gt;i&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&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%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2A-C4604ZjmRx9MB-MjS4KbA%402x.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%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2A-C4604ZjmRx9MB-MjS4KbA%402x.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Created:&lt;/strong&gt; elements from &lt;em&gt;W&lt;/em&gt;’ without an assignment to elements in &lt;em&gt;W&lt;/em&gt;, thus, they have been created in version &lt;em&gt;n&lt;/em&gt; + &lt;em&gt;i&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&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%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2Aj28mAjTQsT96aG4aAuKhBA%402x.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%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2Aj28mAjTQsT96aG4aAuKhBA%402x.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Maintained:&lt;/strong&gt; elements from &lt;em&gt;W&lt;/em&gt; which are still in &lt;em&gt;W&lt;/em&gt;’, but that may have been modified.&lt;/li&gt;
&lt;/ul&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%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2AJcNFxfjJcqhH9V0Pvqe1Gg%402x.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%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2AJcNFxfjJcqhH9V0Pvqe1Gg%402x.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If a test case uses elements from set &lt;em&gt;D&lt;/em&gt;, then the underlying script must be adapted since mandatory elements are missing in the new version. Elements from &lt;em&gt;C&lt;/em&gt; can affect test cases as well; for example, such an element might change the given layout, causing a different XPath somewhere else. It is usually also up to the developer or tester to decide whether these new elements need to be tested. Consequently, the accurate computation of &lt;em&gt;M&lt;/em&gt; is the main interest of the GUI element identification problem. According to the authors, this “generally requires heuristic approaches in the absence of a model where each element has a programmer-defined unique identifier.”&lt;/p&gt;

&lt;p&gt;Selenium offers &lt;a href="http://www.seleniumhq.org/docs/02_selenium_ide.jsp#locating-elements" rel="noopener noreferrer"&gt;various locator types&lt;/a&gt; (e.g. ID, name, or XPath), each with its own pros and cons. Additionally, more advanced test automation frameworks sometimes apply elaborate algorithms to not rely on a single locator. For instance, &lt;a href="https://www.retest.de/" rel="noopener noreferrer"&gt;ReTest&lt;/a&gt;—the company I work for—embraces a novel paradigm called difference testing, where the complete UI state is being captured. As a result, all available attributes can be used at once. Another interesting approach is done by &lt;a href="https://www.testim.io/" rel="noopener noreferrer"&gt;Testim&lt;/a&gt;. They incorporate historical data with the aid of machine learning to rank the locators for each element individually, which stabilizes the tests over time.&lt;/p&gt;

&lt;p&gt;Although these (and other) techniques lead to a quite robust element recognition, they are no silver bullet … and I doubt the current state of the art offers one. But they shift the burden of the GUI element identification problem from humans to machines—reducing the amount of &lt;code&gt;NoSuchElementException&lt;/code&gt;s (or whatever they are called by your framework of choice) developers and testers have to deal with.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>ui</category>
      <category>selenium</category>
      <category>computerscience</category>
    </item>
  </channel>
</rss>
