<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Optivem Journal: Automated Testing]]></title><description><![CDATA[Overview of test types]]></description><link>https://journal.optivem.com/s/test-automation</link><image><url>https://substackcdn.com/image/fetch/$s_!0CjJ!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F9abead4c-3f54-46b1-96aa-7033849416df_200x200.png</url><title>Optivem Journal: Automated Testing</title><link>https://journal.optivem.com/s/test-automation</link></image><generator>Substack</generator><lastBuildDate>Mon, 11 May 2026 09:20:27 GMT</lastBuildDate><atom:link href="https://journal.optivem.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Valentina Jemuović, Optivem]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[optivem@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[optivem@substack.com]]></itunes:email><itunes:name><![CDATA[Valentina Jemuović]]></itunes:name></itunes:owner><itunes:author><![CDATA[Valentina Jemuović]]></itunes:author><googleplay:owner><![CDATA[optivem@substack.com]]></googleplay:owner><googleplay:email><![CDATA[optivem@substack.com]]></googleplay:email><googleplay:author><![CDATA[Valentina Jemuović]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Unit Tests are NOT enough!]]></title><description><![CDATA[You have 100% coverage. All the unit tests are passing. But then, in production, a horrible bug happened.]]></description><link>https://journal.optivem.com/p/unit-tests-are-not-enough-592</link><guid isPermaLink="false">https://journal.optivem.com/p/unit-tests-are-not-enough-592</guid><dc:creator><![CDATA[Valentina Jemuović]]></dc:creator><pubDate>Tue, 21 Apr 2026 06:02:43 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/f0d842e1-0a1f-49b1-9513-47cb1ac33f8c_1000x666.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>&#128075; <em>Hello, this is Valentina with the free edition of the Optivem Journal. I help Engineering Leaders &amp; Senior Software Developers apply <a href="https://journal.optivem.com/p/tdd-in-legacy-code-transformation">TDD in Legacy Code</a>.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://journal.optivem.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://journal.optivem.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><p><strong>The Unit Test Passed. The Customer Was Overcharged.</strong></p><p><strong>Your unit tests can&#8217;t catch this category of bug. Here&#8217;s proof.</strong></p><p>Before, I showed you how Marco&#8217;s team shipped a <a href="https://journal.optivem.com/p/unit-tests-passed-the-bug-shipped">broken tax calculation despite having green tests across the board</a>.</p><p>I received this question:</p><p><em>&#8220;Can you show me the actual code? I want to prove this to my team.&#8221;</em></p><p>So here it is. A concrete example you can drop into any conversation about test strategy.</p><h2>The Setup</h2><p>We have a simple e-commerce system. When a customer places an order, the system needs to look up the tax rate from an external Tax API and calculate the total.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;java&quot;,&quot;nodeId&quot;:&quot;7184c6d1-86db-4218-8bae-50b25475194b&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-java">public class TaxGateway {
    private final HttpClient httpClient;

    public double getTaxRate(String countryCode) {
        HttpResponse response = httpClient.get(
            "https://tax-api.example.com/rates/" + countryCode
        );
        JsonObject json = JsonParser.parse(response.getBody());
        return json.getDouble("rate");
    }
}</code></pre></div><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;java&quot;,&quot;nodeId&quot;:&quot;d4d70deb-55b1-407d-a362-fad2363bb3a8&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-java">public class OrderService {
    private final TaxGateway taxGateway;

    public Order placeOrder(String countryCode, double unitPrice, int quantity) {
        double basePrice = unitPrice * quantity;
        double taxRate = taxGateway.getTaxRate(countryCode);
        double taxAmount = basePrice * taxRate;
        return new Order(basePrice, taxAmount, basePrice + taxAmount);
    }
}</code></pre></div><p>The code looks correct. <code>OrderService</code> calls <code>TaxGateway</code>, which makes an HTTP call to the external Tax API. Everything is wired up properly.</p><p>But there&#8217;s a hidden bug. The Tax API returns rates as whole numbers &#8212; <code>{ "rate": 8 }</code> for 8%. The <code>TaxGateway</code> reads this value and returns it directly. It should divide by 100 first, but it doesn&#8217;t.</p><h2>The Unit Test: GREEN &#9989;</h2><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;java&quot;,&quot;nodeId&quot;:&quot;fb847ace-c321-44db-b0a9-bc7aa2b917e6&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-java">@Test
void shouldApplyTaxRateFromExternalService() {
    when(taxGatewayMock.getTaxRate("US"))
        .thenReturn(0.08);

    Order order = orderService.placeOrder("US", 20.00, 5);

    assertEquals(100.00, order.getBasePrice());
    assertEquals(8.00, order.getTaxAmount());
    assertEquals(108.00, order.getTotalPrice());
}</code></pre></div><p>This test passes. And it <em>should</em> pass &#8212; given the mock&#8217;s return value, the math is perfect.</p><p>The developer sees green. CI sees green. The PR gets approved.</p><p>But the mock is a lie. It returns <code>0.08</code> because that&#8217;s what the developer <em>assumed</em> <code>TaxGateway</code> would return. The mock replaces the entire <code>TaxGateway</code> &#8212; the HTTP call never happens, the JSON parsing never runs, and the missing <code>/ 100.0</code> is never exposed.</p><p>In production, the customer orders $100 worth of products and gets charged <strong>$900</strong> &#8212; because <code>100 * 8 = 800</code> in tax.</p><p>And here&#8217;s the thing: you can&#8217;t fix this with more unit tests. You could unit test every single class &#8212; <code>OrderService</code>, <code>TaxGateway</code> &#8212; and they would all pass. The bug lives at the boundary between your code and the real world, and unit tests <em>must</em> mock that boundary. If the mock is wrong, every test built on top of it is wrong too.</p><h2>The Acceptance Test: RED &#10060;</h2><p>Now here&#8217;s the same scenario written as an acceptance test:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;java&quot;,&quot;nodeId&quot;:&quot;40fa9b64-0afc-4664-8041-7d119108da56&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-java">@Test
void shouldCalculateCorrectTotalWithCountryTaxRate() {
    scenario
        .given().product()
            .withUnitPrice("20.00")
        .and().country()
            .withCode("US")
            .withTaxRate("8%")
        .when().placeOrder()
            .withQuantity("5")
            .withCountry("US")
        .then().shouldSucceed()
        .and().order()
            .hasBasePrice("100.00")
            .hasTaxAmount("8.00")
            .hasTotalPrice("108.00");
}</code></pre></div><p>This test runs against the real system &#8212; real backend, real database, real <code>TaxGateway</code> code &#8212; but with a <strong>stub</strong> for the external Tax API. The <code>given().country().withTaxRate("8%")</code> line configures the Tax API Stub to return <code>{ "rate": 8 }</code> &#8212; exactly what the real Tax API would return.</p><p>The real <code>TaxGateway</code> code executes. The HTTP call fires against the Tax API Stub. The JSON is parsed. And the missing <code>/ 100.0</code> is exposed.</p><p><strong>Result: FAILS.</strong></p><pre><code><code>Expected taxAmount: 8.00
Actual taxAmount:   800.00

Expected totalPrice: 108.00
Actual totalPrice:   900.00</code></code></pre><p>The Tax API Stub returned <code>{ "rate": 8 }</code>, just like the real API would. <code>TaxGateway</code> read the value and returned <code>8</code> directly to <code>OrderService</code>, which calculated <code>100 * 8 = 800</code> in tax. In the unit test, the mock hid this by returning <code>0.08</code> directly. In the acceptance test, the real code path runs and the bug is caught.</p><h2>Why Unit Tests Can Never Catch This</h2><p>The bug isn&#8217;t in <code>OrderService</code>. The math is correct. The wiring is correct. The bug is inside <code>TaxGateway</code> &#8212; in how it parses the external API response.</p><p>But the unit test for <code>OrderService</code> mocks out <code>TaxGateway</code> entirely. The HTTP call never fires. The JSON parsing never runs. The bug is invisible.</p><p><strong>The unit test:</strong></p><ul><li><p>Tests <code>OrderService</code> in isolation</p></li><li><p>Replaces <code>TaxGateway</code> with a mock</p></li><li><p>The mock returns what the developer <em>assumes</em> the gateway returns</p></li><li><p>The real HTTP call and JSON parsing never execute</p></li><li><p>Can&#8217;t catch a bug inside the mocked component</p></li></ul><p><strong>The acceptance test:</strong></p><ul><li><p>Tests the full feature against the real system with stubs for external dependencies</p></li><li><p>The real <code>TaxGateway</code> code runs &#8212; HTTP call, JSON parsing, everything</p></li><li><p>The Tax API Stub behaves like the real Tax API &#8212; returning <code>{ "rate": 8 }</code></p></li><li><p>Catches bugs anywhere in the chain, not just in the class under test</p></li></ul><p>Unit tests verify your logic given your assumptions. Acceptance tests verify the feature works regardless of your assumptions. No amount of unit testing can catch a bug that&#8217;s hidden behind a mock.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8jew!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2efd618e-1b86-4668-96bf-44e0fda2ffb0_964x1142.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8jew!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2efd618e-1b86-4668-96bf-44e0fda2ffb0_964x1142.png 424w, https://substackcdn.com/image/fetch/$s_!8jew!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2efd618e-1b86-4668-96bf-44e0fda2ffb0_964x1142.png 848w, https://substackcdn.com/image/fetch/$s_!8jew!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2efd618e-1b86-4668-96bf-44e0fda2ffb0_964x1142.png 1272w, https://substackcdn.com/image/fetch/$s_!8jew!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2efd618e-1b86-4668-96bf-44e0fda2ffb0_964x1142.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8jew!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2efd618e-1b86-4668-96bf-44e0fda2ffb0_964x1142.png" width="964" height="1142" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2efd618e-1b86-4668-96bf-44e0fda2ffb0_964x1142.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1142,&quot;width&quot;:964,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:127085,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://journal.optivem.com/i/191975581?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2efd618e-1b86-4668-96bf-44e0fda2ffb0_964x1142.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!8jew!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2efd618e-1b86-4668-96bf-44e0fda2ffb0_964x1142.png 424w, https://substackcdn.com/image/fetch/$s_!8jew!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2efd618e-1b86-4668-96bf-44e0fda2ffb0_964x1142.png 848w, https://substackcdn.com/image/fetch/$s_!8jew!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2efd618e-1b86-4668-96bf-44e0fda2ffb0_964x1142.png 1272w, https://substackcdn.com/image/fetch/$s_!8jew!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2efd618e-1b86-4668-96bf-44e0fda2ffb0_964x1142.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>But Wait &#8212; How Do We Know the Stub Is Correct?</h2><p>Fair question. If the acceptance test uses a Tax API Stub instead of the real Tax API, couldn&#8217;t the stub itself be wrong?</p><p>That&#8217;s where <strong>contract tests</strong> come in. A contract test runs the same scenarios against both the real Tax API and the Tax API Stub, and verifies they return the same results. If the stub drifts from reality, the contract test fails.</p><p>So the full safety net looks like this:</p><ul><li><p><strong>Unit tests</strong> verify each component&#8217;s logic in isolation</p></li><li><p><strong>Acceptance tests</strong> verify the feature works end-to-end, using stubs for external systems</p></li><li><p><strong>Contract tests</strong> verify the stubs behave like the real external systems</p></li></ul><p>Each layer catches a different category of bug. Skip any one of them, and you have a blind spot.</p><h2>This Isn&#8217;t an Edge Case</h2><p>The bug in our example was a wrong assumption about the API response format. But this is just one of many ways external system integration breaks:</p><ul><li><p><strong>Wrong format assumption</strong> &#8212; The Tax API returns <code>{ "rate": 8 }</code> meaning 8%, but your code treats it as <code>0.08</code>. Your mock returns whatever you assumed, so the unit test passes.</p></li><li><p><strong>Hardcoded value</strong> &#8212; The developer hardcoded <code>return 0.10</code> inside <code>TaxGateway</code> while building the feature, planning to wire up the HTTP call &#8220;later.&#8221; Later never came. The unit test mocks out <code>TaxGateway</code> entirely, so the hardcoded value is never executed.</p></li><li><p><strong>Wrong field</strong> &#8212; The API returns <code>{ "taxRate": 8, "importRate": 12 }</code> and your code reads <code>importRate</code> instead of <code>taxRate</code>. Your mock only returns the field you expected, so the unit test passes.</p></li><li><p><strong>Stale mapping</strong> &#8212; The API used to return <code>{ "rate": 8 }</code> but v2 changed it to <code>{ "tax": { "rate": 8 } }</code>. Your code still reads the top-level field. Your mock still returns the old format, so the unit test passes.</p></li></ul><p>This pattern shows up constantly across all types of external integrations:</p><ul><li><p>A <strong>payment gateway</strong> that returns amounts in cents, but your code treats them as dollars.</p></li><li><p>A <strong>shipping API</strong> that changed its response format in v2, but your mocks still return v1.</p></li><li><p>An <strong>inventory service</strong> that returns <code>"OUT_OF_STOCK"</code> as a string, but your mock returns a boolean <code>false</code>.</p></li><li><p>A <strong>currency API</strong> that returns rates with 6 decimal places, but your mock rounds to 2.</p></li></ul><p>Every one of these passes unit tests &#8212; because the mock <em>is</em> the assumption. If the assumption is wrong, the mock is wrong, and the test is worthless.</p><p>Every one of these ships to production. Every one of these gets caught by acceptance tests.</p><h2>The Takeaway</h2><p>Unit tests answer: <em>&#8220;Does this component do its job correctly, given my assumptions?&#8221;</em></p><p>Acceptance tests answer: <em>&#8220;Does this feature work the way the customer expects?&#8221;</em></p><p>Contract tests answer: <em>&#8220;Are my assumptions about external systems correct?&#8221;</em></p><p>These are fundamentally different questions. If you&#8217;re only asking the first one, you&#8217;re leaving the other two for your customers to answer.</p><h2>Want to learn how to write acceptance tests like this?</h2><p>I&#8217;m running a live workshop: <strong><a href="https://optivem.thinkific.com/products/courses/2026-05-27-acceptance-testing-workshop">Stop Shipping Bugs: Acceptance Tests Workshop</a>.</strong></p><p>4 hours. Two evenings. Live on Zoom, with me.</p><p>&#9889; I&#8217;ll walk you through the full architecture &#8212; DSL, Drivers, how it all fits together &#8212; and by the end, you&#8217;ll have written a real acceptance test from scenario to assertion.</p><p>&#128197; May 25-26, 2:00-4:00 PM CET</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://optivem.thinkific.com/products/courses/2026-05-27-acceptance-testing-workshop&quot;,&quot;text&quot;:&quot;Join the workshop &#8594;&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://optivem.thinkific.com/products/courses/2026-05-27-acceptance-testing-workshop"><span>Join the workshop &#8594;</span></a></p><p>Limited spots. Register now with the early bird discount - <strong>100 EUR off with code EARLYBIRD100</strong></p><p>&#8212; Valentina</p>]]></content:encoded></item><item><title><![CDATA[Code Coverage ≠ Quality]]></title><description><![CDATA[Why ATDD Beats Code Coverage Metrics]]></description><link>https://journal.optivem.com/p/code-coverage-doesnt-equal-quality</link><guid isPermaLink="false">https://journal.optivem.com/p/code-coverage-doesnt-equal-quality</guid><dc:creator><![CDATA[Valentina Jemuović]]></dc:creator><pubDate>Tue, 13 Jan 2026 07:02:12 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/0cf4a630-654d-4849-8fc3-da951cbb1b56_1000x666.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>&#128075; <em>Hello, this is Valentina with the free edition of the Optivem Journal. I help Engineering Leaders &amp; Senior Software Developers apply <a href="https://journal.optivem.com/p/tdd-in-legacy-code-transformation">TDD in Legacy Code</a>.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://journal.optivem.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://journal.optivem.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><p>Hitting 100% code coverage doesn&#8217;t mean your code works. Here&#8217;s why ATDD matters.</p><p>I remember when my client&#8217;s team first got obsessed with code coverage.</p><p>&#8220;Let&#8217;s hit 90% coverage this sprint!&#8221; the manager said.</p><p>Great, right? Except&#8230; two months later, they had 95% coverage and yet the system kept breaking in production.</p><p>I learned something hard that day: <strong>coverage is just a number</strong>.</p><p>It doesn&#8217;t tell you if your code works, if your business rules are correct, or if anything is maintainable.</p><p>You can execute every line of code and still ship disasters.</p><h2>Knight Capital Group &#8211; $440&#8239;million loss in 45 minutes</h2><p>Here&#8217;s one incident that still keeps me up at night.</p><p>In 2012, Knight Capital Group deployed an update to their trading system.</p><p>An old, previously disabled piece of logic got re&#8209;activated by accident.</p><p>The system <strong>started sending orders it shouldn&#8217;t have.</strong></p><p>Within <strong>45 minutes</strong>, they lost <strong>$440 million</strong>. Just like that.</p><p>Here&#8217;s the kicker:</p><p>No amount of <em>code coverage</em>&#8212;90%, 95%, or 100%&#8212;would have prevented the disaster.</p><p>Why? Because this wasn&#8217;t a line&#8209;not&#8209;executed problem. Only <strong>Acceptance Tests</strong> could have caught this before it hit production.</p><p>Metrics can make you <em>feel safe</em>. Tests that focus on behavior actually <em>keep you safe</em>.</p><h2>Code Coverage is a Trap</h2><p>Code coverage only tells you code ran.</p><p>Not that it worked.</p><p><strong>Running code &#8800; verifying behavior</strong>.</p><p>I learned: chasing metrics doesn&#8217;t make you a better developer&#8212;thinking in terms of behavior does.</p><h2>Metrics &#8800; Safety</h2><p>Next time someone asks about coverage, ask: &#8220;Does it actually tell me my system works?&#8221;</p><blockquote><p>If the answer is no, stop worrying about the percentage and start thinking about behavior.</p></blockquote><div><hr></div><p>This is exactly why I rely on Acceptance Tests. Unit Tests with 100% code coverage are not enough.</p><p>They protect you from the stuff metrics can&#8217;t see&#8212;accidental behavior changes, re-activated logic, &#8220;how did this even happen?&#8221; bugs.</p><p>If you want to learn how to write acceptance tests that make production failures boring instead of catastrophic&#8230;</p><p>&#128640; Join me for <strong>Acceptance Testing (Live Training) </strong>on Wed 25th Feb (17:00 - 19:00 CET). </p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://optivem.thinkific.com/products/live_events/2026-02-25-acceptance-testing-live-training&quot;,&quot;text&quot;:&quot;&#127942; Register now&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://optivem.thinkific.com/products/live_events/2026-02-25-acceptance-testing-live-training"><span>&#127942; Register now</span></a></p><p><em>P.S. Regular price: $97 (free access for Optivem Journal paid subscribers - see event description for details)</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://journal.optivem.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://journal.optivem.com/subscribe?"><span>Subscribe now</span></a></p>]]></content:encoded></item><item><title><![CDATA[Modern TDD - System Level]]></title><description><![CDATA[Teams who adopt automated System Tests tend to write them at the end of the Sprint. Developers & QA Engineers discover (late) they misunderstood the requirements! This problem can be solved with ATDD.]]></description><link>https://journal.optivem.com/p/modern-tdd-system-level</link><guid isPermaLink="false">https://journal.optivem.com/p/modern-tdd-system-level</guid><dc:creator><![CDATA[Valentina Jemuović]]></dc:creator><pubDate>Fri, 27 Jun 2025 06:01:37 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/f5c1b751-3e88-4f03-b78b-73e30f0df1c7_1000x666.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>&#128274; Welcome to the premium Optivem Journal. I&#8217;ll help you apply TDD to escape the nightmare of Legacy Code. Join our paid community of 160+ senior engineers &amp; leaders for support on your TDD journey, plus instant access to group chat and live Q&amp;As:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://journal.optivem.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://journal.optivem.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><p>Previously, we covered the <a href="https://journal.optivem.com/p/modern-test-pyramid-system-level">Modern Test Pyramid - System Level</a>, where we showed the importance of System Level tests, which included Smoke Tests, E2E Tests, and most importantly, Acceptance Tests &amp; External System Contract Tests.</p><p>Acceptance Tests are executable Acceptance Criteria. We learnt that Acceptance Tests &amp; External System Contract Tests, together, are a replacement for Manual System Regression Testing.</p><p>Does it matter whether we write Acceptance Tests last&#8230; or write Acceptance Tests first?</p><div><hr></div><p>&#128226; On <strong>Wed 9th July 17:00 CET</strong>, I&#8217;m hosting <strong>TDD &amp; Unit Tests - Part 4 (Live Q&amp;A)</strong>:</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://lu.ma/0l194lm9&quot;,&quot;text&quot;:&quot;Register now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://lu.ma/0l194lm9"><span>Register now</span></a></p><p><em>P.S. If you&#8217;re a Paid Member, you&#8217;ll receive a 100% discount (see Event Description for instructions on how to redeem your 100% discount).</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://journal.optivem.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://journal.optivem.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2>Approach 1. Writing &amp; Executing Manual Tests Last</h2><p>Most companies are NOT agile, but rather they work in a Waterfall way. They might be practicing Scrum in a non-agile way, whereby each Sprint is a mini-waterfall. <em>(Or perhaps the whole release is a waterfall, whereby a one phase is executed over multiple sprints.)</em></p><ol><li><p>PO specifies User Stories</p></li><li><p>PO hands over the User Stories to Developers</p></li><li><p>Developers try to implement the User Stories <em>(based on their interpretation)</em></p></li><li><p>Developers hand over the Software to QA Engineers</p></li><li><p>QA Engineers test the User Stories <em>(based on their interpretation)</em></p></li></ol><p>Here&#8217;s a more detailed breakdown of the mini-waterfall:</p><h4>Requirement Phase</h4><ul><li><p>PO specifies User Stories</p></li></ul><h4>Development Phase</h4><ol><li><p>Developers try to implement the User Stories</p></li><li><p>Developers <strong>manually test</strong> the User Stories on their local machine</p></li></ol><h4>QA Phase</h4><ol><li><p>Deploy System to QA Environment</p></li><li><p>User Story Testing</p><ol><li><p>QA Engineers <strong>manually test the User Stories</strong> (from the Sprint Backlog)</p></li><li><p>Developers fix any bugs reported</p></li><li><p>QA Engineers <strong>manually test the fixes</strong></p></li><li><p>If QA Engineers find further bugs, then repeat the process (of <strong>manual testing</strong> &amp; developer rework)</p></li></ol></li><li><p>Regression Testing</p><ol><li><p>QA Engineers perform <strong>manual regression testing</strong></p></li><li><p>Developers fix any regression bugs reported</p></li><li><p>QA Engineers <strong>manually test the fixes</strong></p></li><li><p>If QA Engineers find further bugs, then repeat the process (of <strong>manual testing</strong> &amp; developer rework)</p></li></ol></li></ol><p><strong>Problems of Manual Tests Last:</strong></p><p>The following are the problems faced (at the end of the Sprint):</p><ul><li><p>Regression Bugs - QA Engineers discover lots of Regression Bugs. Time Wasted: Developers fixing &amp; QA Engineers re-testing regression bugs.</p></li><li><p>Misunderstood Requirements - Developers discover that QA Engineers had a different interpretation of requirements. Time Wasted: Late Developer rework due to misinterpretations &amp; QA Engineers re-testing.</p></li><li><p>Missing Scenarios - QA Engineers discover new scenarios that Developers didn&#8217;t think of. Time Wasted: Late Developer rework due to missed scenarios &amp; QA Engineers re-testing.</p></li></ul><h2>Approach 2. Writing Acceptance Tests last</h2><p>When companies adopt Acceptance Tests, to replace Manual Regression Tests, they tend to keep the same process of working, i.e. at the end of the Sprint, QA Engineers now write (automated) Acceptance Tests rather than Manual Tests.</p><p><strong>Problems solved</strong></p><p>Writing Acceptance Tests solves the problem:</p><ul><li><p>Regression Bugs are not detected by QA Engineer, but are rather visible to the Developer hence solved by the Developer (hence QA Engineer has time for reporting new bugs rather than regression bugs).</p></li></ul><p><em>Note: Acceptance Tests help reduce regression bugs associated with User Story Acceptance Criteria. For example, if we implement some Acceptance Criteria in Sprint N, then we&#8217;ll be protected in all future Sprints (Sprint N+1, Sprint N + 2, etc.)</em></p><p><strong>Problems NOT solved</strong></p><p>However, since Acceptance Tests are written at the end of the Sprint, it does not solve requirement-related problems, where there&#8217;s a gap in requirement understanding between Developers &amp; QA Engineers (and also PO):</p><ul><li><p>Misunderstood Requirements - This problem is still not solved!</p></li><li><p>Missing Scenarios - This problem is still not solved!</p></li></ul><p>There&#8217;s also a new problem:</p><ul><li><p>Invalid Tests - When writing the test at the end, since the functionality has already been implemented, we tend to write just enough of the test to see it GREEN. It could happen by accident, that we write an Acceptance Test that executes the System but does NOT verify anything (ZERO assertions!); we see the test is passing, and we move on&#8230; but this test is NOT testing anything at all! Alternatively, the test could have an assertion, but it might be the wrong assertion; it is not verifying what should be verified. It&#8217;s an always-passing test. This is a useless test, because it gives us a false sense of assurance; it does not protect us against regression bugs!</p></li></ul><h2>Approach 3. Writing Acceptance Tests first (ATDD)</h2><p>How can we address the issue of requirement misunderstandings? How do we bring everyone (PO, Developers, QA Engineers) on the same page? </p><p>Requirement misunderstandings occur because requirements are often generalized, leaving room for misinterpretation and gaps in understanding.</p><p>What if we could write requirements in a very specific way, such that there is no room for misinterpretation? What if we could write requirements clearly, specifying behavioral expectations through specific inputs and expected outputs, i.e. example-based requirements?</p><p>If we wrote example-based requirements before coding, then it puts everyone on the same page. Acceptance Tests themselves are example-based requirements. Writing them before coding is known as ATDD.</p><p><strong>Problems solved:</strong></p><p>Writing example-based requirements (Acceptance Tests) before coding helps align the whole team regarding requirements:</p><ul><li><p>Misunderstood Requirements - Writing requirements as examples clarifies them for everyone and eliminates gaps in understanding.</p></li><li><p>Missing Scenarios - QA Engineers can bring their creative thinking (&#8220;what if&#8220; scenarios) to be brainstormed at the start of the Sprint, which is converted to requirements as examples, so that the whole team has a more comprehensive understanding of scenarios that need to be covered</p></li><li><p>Invalid Tests - By writing the Acceptance Test first, we can verify that it fails and that the failure occurs for the expected reason. This assures us that the test itself is valid, that it&#8217;s testing what it should be testing.</p></li></ul>
      <p>
          <a href="https://journal.optivem.com/p/modern-tdd-system-level">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Modern Test Pyramid - System Level]]></title><description><![CDATA[Many teams are stuck with slow QA, waiting days/weeks for QA Engineers to test User Stories as well as Regression Testing. The feedback loop is too slow. Can we have much faster feedback?]]></description><link>https://journal.optivem.com/p/modern-test-pyramid-system-level</link><guid isPermaLink="false">https://journal.optivem.com/p/modern-test-pyramid-system-level</guid><dc:creator><![CDATA[Valentina Jemuović]]></dc:creator><pubDate>Fri, 09 May 2025 06:01:38 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/1ea1ccd1-58fa-4d48-9d2a-840a6184041d_1000x666.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>&#128274; Welcome to the premium Optivem Journal. I&#8217;ll help you apply TDD to escape the nightmare of Legacy Code. Join our paid community of 160+ senior engineers &amp; leaders for support on your TDD journey, plus instant access to group chat and live Q&amp;As:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://journal.optivem.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://journal.optivem.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2>Manual System Regression Testing = Waste!</h2><p>The default approach that most companies still rely on is Manual System Testing, which is done by QA Engineers at the end of the Sprint &amp; also in preparation for the Release.</p><h4>Problem #1: Slow Delivery</h4><ul><li><p><strong>Developer Time Wasted - Manual Regression Testing:</strong> During Sprints, as Developers implement User Stories, they also need to do some basic Manual Regression Testing to make sure their User Stories didn&#8217;t break anything. <em>Generally, they do very basic Manual Regression Testing, it is not extensive, maybe just a few basic scenarios.</em></p></li><li><p><strong>QA Engineer Time Wasted - Manual Regression Testing:</strong> At the end of the Sprint, QA Engineers need to test User Stories and do some basic Manual Regression Testing. Furthermore, prior to releasing the System, they need to execute the Manual Regression Test suite to make sure there&#8217;s no regression bugs.</p></li><li><p><strong>Developer Time Wasted - Expensive Late Rework:</strong> Since Developers have to wait for the QA Engineers to perform the time-consuming Manual Regression Testing</p></li></ul><p>The impact of the time wasted is that we have a high internal cost; we&#8217;re throwing money down the drain; we&#8217;re paying our developers &amp; QA Engineers to waste time; the team spends more time on bugs rather than features.</p><h4>Problem #2: Buggy Releases</h4><ul><li><p><strong>Customer-facing Regression Bugs:</strong> Prior to the Release, the QA Engineers should do &#8220;full&#8220; Regression Testing (and keep on repeating that until Developers have resolved all Regression Bugs). However, in practice, that is infeasible - because Manual Regression Testing is too slow; the company can&#8217;t hire an infinite number of QA Engineers; the company can&#8217;t indefinitely postpone a release due to repeated Manual Regression Test cycles. So what&#8217;s the pragmatic solution? QA Engineers are forced to cut corners - execute only &#8220;partial&#8220; Regression Testing, rather than &#8220;full&#8220; Regression Testing. This causes Regression Bugs to escape to Customers, to be reported to the Customer Support Team.</p></li></ul><p>The impact of customer-facing bugs is that customers become dissatisfied, leading to potential customer loss (hence lost revenue). Furthermore, it can cause poor reputation in the market, thus causing loss of potential future clients (hence losing potential future revenue).</p><div><hr></div><p>&#128226; On <strong>Wed 9th July 17:00 CET</strong>, I&#8217;m hosting <strong>TDD &amp; Unit Tests - Part 4 (Live Q&amp;A)</strong>:</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://lu.ma/0l194lm9&quot;,&quot;text&quot;:&quot;Register now&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://lu.ma/0l194lm9"><span>Register now</span></a></p><p><em>P.S. If you&#8217;re a Paid Member, you&#8217;ll receive a 100% discount (see Event Description for instructions on how to redeem your 100% discount).</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://journal.optivem.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://journal.optivem.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2>Automated System Regression Testing = Solution</h2><h4>Impact #1: Faster Delivery</h4><ul><li><p>Developers do NOT have to do Manual Testing of their User Stories and don&#8217;t have to do Manual Regression Testing either. This reduces Developer time spent per User Story.</p></li><li><p>QA Engineers do NOT execute Manual Regression Testing. Instead, they just do Exploratory Testing (i.e. creative testing).</p></li><li><p>Developers incur LOW cost of rework. Even if Developers introduce a Bug, they will discover it quickly through Automated System Tests (within &lt;= 1hr) </p></li></ul><p>The impact of this is that we have lower internal cost of change, hence we can spend more time on features rather than bug fixes, and we can deliver faster.</p><h4>Impact #2: Working Releases</h4><ul><li><p>No more Customer Regression Bugs! With Automated System Tests, we can be sure that the full suite is always executed.</p></li></ul><p>The impact of this is that customers can trust our software, leading to increased customer retention, hence we can maintain our revenue consistently. Furthermore, it aids customer referrals and positive brand image, hence increasing the number of new customers we get, hence increased revenue.</p><h2>Modern Test Pyramid - System Level</h2><p>Here&#8217;s the Modern System Test Pyramid:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mSVi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff786f506-e482-46a2-8186-eddbefbd9588_1057x739.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mSVi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff786f506-e482-46a2-8186-eddbefbd9588_1057x739.png 424w, https://substackcdn.com/image/fetch/$s_!mSVi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff786f506-e482-46a2-8186-eddbefbd9588_1057x739.png 848w, https://substackcdn.com/image/fetch/$s_!mSVi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff786f506-e482-46a2-8186-eddbefbd9588_1057x739.png 1272w, https://substackcdn.com/image/fetch/$s_!mSVi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff786f506-e482-46a2-8186-eddbefbd9588_1057x739.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mSVi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff786f506-e482-46a2-8186-eddbefbd9588_1057x739.png" width="1057" height="739" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f786f506-e482-46a2-8186-eddbefbd9588_1057x739.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:739,&quot;width&quot;:1057,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:55285,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://journal.optivem.com/i/160862357?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff786f506-e482-46a2-8186-eddbefbd9588_1057x739.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mSVi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff786f506-e482-46a2-8186-eddbefbd9588_1057x739.png 424w, https://substackcdn.com/image/fetch/$s_!mSVi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff786f506-e482-46a2-8186-eddbefbd9588_1057x739.png 848w, https://substackcdn.com/image/fetch/$s_!mSVi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff786f506-e482-46a2-8186-eddbefbd9588_1057x739.png 1272w, https://substackcdn.com/image/fetch/$s_!mSVi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff786f506-e482-46a2-8186-eddbefbd9588_1057x739.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Let&#8217;s see how we can write effective System Level Tests:</p><ul><li><p>Smoke Tests</p></li><li><p>E2E Tests</p></li><li><p>Acceptance Tests</p></li><li><p>External System Contract Tests</p></li></ul>
      <p>
          <a href="https://journal.optivem.com/p/modern-test-pyramid-system-level">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[🏆TDD in Legacy Code - Acceptance Tests & External System Contract Tests (Summary)]]></title><description><![CDATA[Acceptance Tests verify System Behavior. How do we separate System Behavior from System Structure using the Four Layer Model?]]></description><link>https://journal.optivem.com/p/acceptance-tests-and-external-system-contract-tests</link><guid isPermaLink="false">https://journal.optivem.com/p/acceptance-tests-and-external-system-contract-tests</guid><dc:creator><![CDATA[Valentina Jemuović]]></dc:creator><pubDate>Fri, 28 Mar 2025 07:01:37 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/27a87fb3-5171-401e-b76e-de20e4c304e7_1000x666.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>&#128226; My <strong>next Live Q&amp;A Session</strong> about <strong>Unit Tests </strong>is on Wed 30th April 17:00. If you&#8217;re an Optivem Journal paid member, <a href="https://lu.ma/hhmu38v1">get your 100% discount ticket</a>.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://lu.ma/hhmu38v1&quot;,&quot;text&quot;:&quot;Register now&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://lu.ma/hhmu38v1"><span>Register now</span></a></p><p>Upgrade to join the Live Q&amp;A for free:</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://journal.optivem.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://journal.optivem.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><p>Acceptance Tests help us verify System Behavior from the User Perspective. Thus, they are business-facing tests.</p><p>Acceptance Tests are black-box tests that are agnostic to the underlying System Architecture. Thus, the Acceptance Tests should remain the same irrespective of whether we have an MVP app, or Frontend &amp; Monolithic Backend, or Frontend &amp; Microservice Backend. It also doesn&#8217;t matter whether our system is well-designed or whether it&#8217;s a Big Ball of Mud. Acceptance Tests don&#8217;t care about this.</p><p>But how do we handle the problem of UX/UI changes when we&#8217;d have to rewrite all our Acceptance Tests? What about when we have multiple channels - e.g. one Web UI, one Mobile UI, and perhaps a public-facing REST API - do we then have to write three tests for each functionality?</p><p>Fortunately, Dave Farley came up with a solution to this problem - if we write tests that are expressed in terms of the domain language (the DSL), rather than being expressed in terms of the UI, we can then write a test that is insensitive to UX/UI changes and such that the single test can be executed against multiple channels (Web UI, Mobile UI, Desktop UI, public REST API). </p><h2>Acceptance Tests - Four Layer Model</h2><p>In the Four Layer Model, the Acceptance Test calls the DSL, which calls the Drivers, and finally the Drivers call the Systems.</p><p>We can see below that the Acceptance Test calls the System DSL to execute operations on the System, and it calls the External System Stub DSL to execute operations on the External System Stub. The DSL is written in the domain language.</p><p>The DSL needs to communicate with the underlying Systems. The System DSL needs to communicate with the System via System Driver(s). The External System Stub DSL needs to communicate with the External System Stub via External System Stub Driver.</p><p><em>Note: Why communicate with the External System Stub, rather than the Real External System? It&#8217;s because the External System Stub enables us to have full control over the External System, we can execute any scenario on the System. This is contrasted with E2E Tests, which do not use Stubs, and thus have limited scenarios that can be executed.</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!u4Xp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bf114b9-1094-45ca-9529-2fc740424b4a_1693x1100.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!u4Xp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bf114b9-1094-45ca-9529-2fc740424b4a_1693x1100.png 424w, https://substackcdn.com/image/fetch/$s_!u4Xp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bf114b9-1094-45ca-9529-2fc740424b4a_1693x1100.png 848w, https://substackcdn.com/image/fetch/$s_!u4Xp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bf114b9-1094-45ca-9529-2fc740424b4a_1693x1100.png 1272w, https://substackcdn.com/image/fetch/$s_!u4Xp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bf114b9-1094-45ca-9529-2fc740424b4a_1693x1100.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!u4Xp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bf114b9-1094-45ca-9529-2fc740424b4a_1693x1100.png" width="1456" height="946" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6bf114b9-1094-45ca-9529-2fc740424b4a_1693x1100.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:946,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:101424,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://journal.optivem.com/i/159838323?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bf114b9-1094-45ca-9529-2fc740424b4a_1693x1100.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!u4Xp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bf114b9-1094-45ca-9529-2fc740424b4a_1693x1100.png 424w, https://substackcdn.com/image/fetch/$s_!u4Xp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bf114b9-1094-45ca-9529-2fc740424b4a_1693x1100.png 848w, https://substackcdn.com/image/fetch/$s_!u4Xp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bf114b9-1094-45ca-9529-2fc740424b4a_1693x1100.png 1272w, https://substackcdn.com/image/fetch/$s_!u4Xp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bf114b9-1094-45ca-9529-2fc740424b4a_1693x1100.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><em>Note: In the image above, there&#8217;s only one External System. If there&#8217;s multiple external systems, then for each one you&#8217;d have a corresponding Stub DSL and Stub Driver (e.g. External System A Stub DSL, External System A Stub Driver).</em></p><p><em>You can read more about Farley&#8217;s <a href="https://dojoconsortium.org/assets/ATDD%20-%20How%20to%20Guide.pdf">Four Layer Model</a>.</em></p><h2>External System Contract Tests - Three Layer Model</h2><p>Above, we saw that Acceptance Tests rely on External System Stubs, rather than connecting to the (real) External System Test Instance.</p><p>But what if the External System Stub doesn&#8217;t match the Real External System? Then, our Acceptance Tests could pass, but yet it wouldn&#8217;t work in production. </p><p>In order to have assurance that our External System Stub matches the Real External System, we need to write External System Contract Tests.</p><p>The External System Contract Test calls the External System Driver. This is done both for the &#8220;Real&#8220; and the &#8220;Stub&#8220; to verify that the &#8220;Stub&#8220; matches the &#8220;Real&#8220;. This provides us assurance that our assumptions about External Systems are correct, thus we can trust our Acceptance Tests.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uTv6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a91106-f10d-473f-90e6-d9157ba1dc65_1386x793.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uTv6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a91106-f10d-473f-90e6-d9157ba1dc65_1386x793.png 424w, https://substackcdn.com/image/fetch/$s_!uTv6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a91106-f10d-473f-90e6-d9157ba1dc65_1386x793.png 848w, https://substackcdn.com/image/fetch/$s_!uTv6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a91106-f10d-473f-90e6-d9157ba1dc65_1386x793.png 1272w, https://substackcdn.com/image/fetch/$s_!uTv6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a91106-f10d-473f-90e6-d9157ba1dc65_1386x793.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uTv6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a91106-f10d-473f-90e6-d9157ba1dc65_1386x793.png" width="1386" height="793" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/37a91106-f10d-473f-90e6-d9157ba1dc65_1386x793.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:793,&quot;width&quot;:1386,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:91127,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://journal.optivem.com/i/159838323?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a91106-f10d-473f-90e6-d9157ba1dc65_1386x793.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!uTv6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a91106-f10d-473f-90e6-d9157ba1dc65_1386x793.png 424w, https://substackcdn.com/image/fetch/$s_!uTv6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a91106-f10d-473f-90e6-d9157ba1dc65_1386x793.png 848w, https://substackcdn.com/image/fetch/$s_!uTv6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a91106-f10d-473f-90e6-d9157ba1dc65_1386x793.png 1272w, https://substackcdn.com/image/fetch/$s_!uTv6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a91106-f10d-473f-90e6-d9157ba1dc65_1386x793.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>Sample User Story</h2><p>Let&#8217;s start with this sample User Story:</p><pre><code>User Story: Place an Order

As a customer, I want to place an order for a product, so that I can purchase items I need.

Acceptance Criteria #1: Successfully place an order for "Apple"
    Given the ERP is set up with the product "APPLE1001" and price $1.99
    When the product "APPLE1001" is added to the cart with quantity 5
    And the customer details are provided with name "John", address "My Street", and card number "123451234512"
    And the order is placed
    Then the order confirmation message should be "You have successfully placed your order"

Acceptance Criteria #2: Fail to place an order due to negative quantity
    Given the ERP is set up with the product "APPLE1001" and price $1.99
    When the product "Apple" is added to the cart with quantity -2
    And the customer details are provided with name "John", address "My Street", and card number "123451234512"
    And the order is placed
    Then an error message should be displayed indicating invalid quantity

Acceptance Criteria #3: ....

...</code></pre><p>Now select the first Acceptance Criteria:</p><pre><code><code>Acceptance Criteria #1: Successfully place an order for "Apple"
    Given the ERP is set up with the product "APPLE1001" and price $1.99
    When the product "APPLE1001" is added to the cart with quantity 5
    And the customer details are provided with name "John", address "My Street", and card number "123451234512"
    And the order is placed
    Then the order confirmation message should be "You have successfully placed order &lt;Order number&gt;"</code></code></pre><p>How do we write the Acceptance Test &amp; External System Test(s)? How do we implement the Test Architecture such that System Behavior is separated from System Structure?</p><p>Let&#8217;s see some examples&#8230;</p>
      <p>
          <a href="https://journal.optivem.com/p/acceptance-tests-and-external-system-contract-tests">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Why E2E Test Initiatives fail]]></title><description><![CDATA[Engineering Managers often try to introduce automated E2E Tests to reduce regression bugs and eliminate manual regression tests. But their initiative fails.]]></description><link>https://journal.optivem.com/p/why-e2e-test-initiatives-fail</link><guid isPermaLink="false">https://journal.optivem.com/p/why-e2e-test-initiatives-fail</guid><dc:creator><![CDATA[Valentina Jemuović]]></dc:creator><pubDate>Mon, 30 Dec 2024 07:00:37 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/42b81bed-4878-4435-89e6-9d15b9f7b23e_1000x666.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>&#128274;Hello, this is Valentina with a premium issue of the Optivem Journal. I help Engineering Leaders &amp; Senior Software Developers apply TDD in Legacy Code. This article is part of the <a href="https://journal.optivem.com/p/tdd-in-legacy-code-outline">TDD in Legacy Code</a> series. To get these articles in your inbox every week, subscribe:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://journal.optivem.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://journal.optivem.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2>Initially, Manual Regression Testing seems OK!</h2><p>When a company is in startup mode, they do everything quickly. The goal is to get customers, get revenue, and get the market position. At this point, all the testing is done manually - maybe just a few hours is enough to do all the manual regression testing. It doesn&#8217;t take up too much time. One QA Engineer is enough. Business is happy.</p><h2>But later, as the product grows, it&#8217;s a nightmare!</h2><p>Then, the company grows. After several years, the software product is bigger and more complex. </p><p>The problems faced are:</p><ul><li><p>Manual Regression Testing takes too long, and even longer</p></li><li><p>Developers spend the majority of their sprint bug fixing, not much on features</p></li><li><p>You have to keep hiring more QA Engineers, but it&#8217;s never enough</p></li></ul><h2>The obvious solution is Automated Testing</h2><p>The &#8220;obvious&#8220; solution to the above is to introduce automated testing. Everyone believes they&#8217;ll get these benefits:</p><ul><li><p>Zero regression bugs going into production</p></li><li><p>No more manual regression testing by QA Engineers</p></li><li><p>Developers will spend most of their time on new features, rather than on bugs</p></li></ul><h2>Let&#8217;s introduce the E2E Test Initiative</h2><p>One common approach used by Engineering Managers is to switch manual QA Engineers to Test Automation Engineers, and to transfer manual QA procedures to E2E Tests. </p><p>This is common in companies who believe that:</p><ul><li><p>It&#8217;s the QA Engineer&#8217;s job to test</p></li><li><p>It&#8217;s the Developer&#8217;s job to code</p></li></ul><p>So then the obvious fix is to optimize the QA Department, which works in silo mode, separated from Developers.</p><p>Engineering Managers might try one of the these things:</p><ul><li><p>Writing E2E Tests that directly use Selenium / Cypress / etc.</p></li><li><p>Using some record-and-playback tools to generate E2E Tests</p></li></ul><p>E2E Tests are attractive because they are highly realistic tests, can detect regression bugs in the System and are in communication with External Systems.</p><h2>Unfortunately, the E2E initiative fails!</h2><p>Initially, everything looks great, the E2E Tests have eliminated Manual QA Regression Testing. </p><p>But then, 3 growing problems occur: </p><ul><li><p><strong>Unreliable regression bug detection:</strong> Initially, the E2E Tests were detecting regression bugs from the end-user perspective, so when an E2E Test failed, developers could fix the regression bug. But later, E2E Tests start failing even though there&#8217;s no regression bugs! Then the developers have to waste time troubleshooting E2E Tests, only to discover they&#8217;ve wasted time, because there&#8217;s no regression bugs!</p></li><li><p><strong>High maintenance cost - wasteful:</strong> Initially, it didn&#8217;t take much time to write the E2E Tests. But later, as the software is changes due to changes in UX/UI design, the E2E Tests start failing even though there&#8217;s no regression bug. The QA Engineer has to waste time updating hundreds of tests due to a change in one UI element.</p></li><li><p><strong>We can&#8217;t test acceptance criteria:</strong>&nbsp;We can test many positive flows, but we&#8217;re quite limited in terms of negative flows. So, for negative flows, we may still need manual QA testing or we wait for user complaints.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Iisn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6e09cfa-e678-45bb-8241-a55c74412714_908x547.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Iisn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6e09cfa-e678-45bb-8241-a55c74412714_908x547.png 424w, https://substackcdn.com/image/fetch/$s_!Iisn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6e09cfa-e678-45bb-8241-a55c74412714_908x547.png 848w, https://substackcdn.com/image/fetch/$s_!Iisn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6e09cfa-e678-45bb-8241-a55c74412714_908x547.png 1272w, https://substackcdn.com/image/fetch/$s_!Iisn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6e09cfa-e678-45bb-8241-a55c74412714_908x547.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Iisn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6e09cfa-e678-45bb-8241-a55c74412714_908x547.png" width="908" height="547" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c6e09cfa-e678-45bb-8241-a55c74412714_908x547.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:547,&quot;width&quot;:908,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:48541,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Iisn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6e09cfa-e678-45bb-8241-a55c74412714_908x547.png 424w, https://substackcdn.com/image/fetch/$s_!Iisn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6e09cfa-e678-45bb-8241-a55c74412714_908x547.png 848w, https://substackcdn.com/image/fetch/$s_!Iisn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6e09cfa-e678-45bb-8241-a55c74412714_908x547.png 1272w, https://substackcdn.com/image/fetch/$s_!Iisn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6e09cfa-e678-45bb-8241-a55c74412714_908x547.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Let&#8217;s dive deeper into these problems, and find out how we can solve them: &#11015;&#65039;&#11015;&#65039;&#11015;&#65039;</p>
      <p>
          <a href="https://journal.optivem.com/p/why-e2e-test-initiatives-fail">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[TDD in Legacy Code - Maintainable External System Contract Tests]]></title><description><![CDATA[Directly referencing the HTTP Client in our External System Contract Tests? This makes the tests very hard to maintain. That's why we need to use Drivers as an abstraction layer.]]></description><link>https://journal.optivem.com/p/maintainable-external-system-contract-tests-in-legacy-code</link><guid isPermaLink="false">https://journal.optivem.com/p/maintainable-external-system-contract-tests-in-legacy-code</guid><dc:creator><![CDATA[Valentina Jemuović]]></dc:creator><pubDate>Fri, 13 Dec 2024 07:00:54 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/33020f78-1d44-4798-9ae9-1dbb02ce931c_1000x666.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>&#128274;Hello, this is Valentina with a premium issue of the Optivem Journal. I help Engineering Leaders &amp; Senior Software Developers apply TDD in Legacy Code. This article is part of the <a href="https://journal.optivem.com/p/tdd-in-legacy-code-outline">TDD in Legacy Code</a> series. To get these articles in your inbox every week, subscribe:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://journal.optivem.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://journal.optivem.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2>Coupling Contract Tests to HTTP Clients</h2><p>When introducing External System Contract into Legacy Code, the most straightforward way is to directly call the HTTP client from the test. </p><h2>What if the External System changes? Nightmare</h2><p>The problem with that approach is that we have External System URLs scattered around everywhere across the tests! If for whatever reason, some endpoint changes on the External System, we may need to update several tests! Or even worse, if we switch from one External System Provider to another, we&#8217;d probably need to completely rewrite all the contract tests.</p><h2>How to write maintainable Contract Tests?</h2><p>That&#8217;s why we need Contract Tests for External Systems which can be executed both against the External System Stubs and against the External System Test Instances.</p><p>I&#8217;ll show you how to add Contract Tests to provide assurance that the External System Stub Drivers are actually valid.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jXGP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c471d4e-0eed-4f2c-bbdb-1b354cc828e7_4820x1239.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jXGP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c471d4e-0eed-4f2c-bbdb-1b354cc828e7_4820x1239.png 424w, https://substackcdn.com/image/fetch/$s_!jXGP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c471d4e-0eed-4f2c-bbdb-1b354cc828e7_4820x1239.png 848w, https://substackcdn.com/image/fetch/$s_!jXGP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c471d4e-0eed-4f2c-bbdb-1b354cc828e7_4820x1239.png 1272w, https://substackcdn.com/image/fetch/$s_!jXGP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c471d4e-0eed-4f2c-bbdb-1b354cc828e7_4820x1239.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jXGP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c471d4e-0eed-4f2c-bbdb-1b354cc828e7_4820x1239.png" width="1456" height="374" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9c471d4e-0eed-4f2c-bbdb-1b354cc828e7_4820x1239.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:374,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:286911,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!jXGP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c471d4e-0eed-4f2c-bbdb-1b354cc828e7_4820x1239.png 424w, https://substackcdn.com/image/fetch/$s_!jXGP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c471d4e-0eed-4f2c-bbdb-1b354cc828e7_4820x1239.png 848w, https://substackcdn.com/image/fetch/$s_!jXGP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c471d4e-0eed-4f2c-bbdb-1b354cc828e7_4820x1239.png 1272w, https://substackcdn.com/image/fetch/$s_!jXGP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c471d4e-0eed-4f2c-bbdb-1b354cc828e7_4820x1239.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Here are the steps to refactor External System Contract Tests in Legacy Code to be more maintainable. I&#8217;ll provide you with step-by-step guidance on how to refactor them in your GitHub Sandbox Project. &#11015;&#65039;&#11015;&#65039;&#11015;&#65039;</p>
      <p>
          <a href="https://journal.optivem.com/p/maintainable-external-system-contract-tests-in-legacy-code">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[External System Contract Tests]]></title><description><![CDATA[External System Contract Tests verify that our System can communicate with External Systems, also providing us assurance that the External System Stubs used in the Acceptance Tests are valid.]]></description><link>https://journal.optivem.com/p/external-system-contract-tests</link><guid isPermaLink="false">https://journal.optivem.com/p/external-system-contract-tests</guid><dc:creator><![CDATA[Valentina Jemuović]]></dc:creator><pubDate>Wed, 11 Dec 2024 07:01:25 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/f9837b56-2067-44d0-85c6-52575daef365_1000x666.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>&#128274;Hello, this is Valentina with a premium issue of the Optivem Journal. I help Engineering Leaders &amp; Senior Software Developers apply TDD in Legacy Code. This article is part of the <a href="https://journal.optivem.com/p/tdd-in-legacy-code-outline">TDD in Legacy Code</a> series. To get these articles in your inbox every week, subscribe:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://journal.optivem.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://journal.optivem.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2>What are External System Contract Tests?</h2><p>External System Contract Tests verify that our System can communicate with External Systems; that we have a valid expectation regarding their contracts. </p><ul><li><p>If the External System Contract Test passes when executed for both the External System Test Instance and External System Stub, the Stub has a matching contract</p></li><li><p>If the External System Contract Test passes when executed against the External System Test instance, but fails when executed against the External System Stub, w need to make corrections to our External System Stub</p></li><li><p>If the External System Contract Test fails when executed against the External System Test Instance, we&#8217;ve got wrong expectations or the External System has changed - we need to update the External System Contract Test and the External System Stub</p></li></ul><p>External System Contract Tests target (and span) the External System Test Instances.</p><ul><li><p>If we have the possibility to deploy the External System Test Instances (e.g. self-hosted ERPNext), then we deploy them to the E2E Environment and run External System Contract Tests on those instances</p></li><li><p>However, if the External System Test Instances already exist outside of our environment (e.g. PayPal Developer Portal), then we run the External System Contract Tests against those instances</p></li></ul><p>For each External System, we would have some External System Contract Tests. As part of test execution, we should be able to &#8220;switch&#8220; the connection between some External System Test Instance and the External System Stub. In that way, the External System Contract Test is written once, but can be executed against both.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!lA1R!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5d64b1f-f1ea-4e7a-9750-ab37b0e72393_872x842.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lA1R!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5d64b1f-f1ea-4e7a-9750-ab37b0e72393_872x842.png 424w, https://substackcdn.com/image/fetch/$s_!lA1R!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5d64b1f-f1ea-4e7a-9750-ab37b0e72393_872x842.png 848w, https://substackcdn.com/image/fetch/$s_!lA1R!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5d64b1f-f1ea-4e7a-9750-ab37b0e72393_872x842.png 1272w, https://substackcdn.com/image/fetch/$s_!lA1R!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5d64b1f-f1ea-4e7a-9750-ab37b0e72393_872x842.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!lA1R!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5d64b1f-f1ea-4e7a-9750-ab37b0e72393_872x842.png" width="872" height="842" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c5d64b1f-f1ea-4e7a-9750-ab37b0e72393_872x842.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:842,&quot;width&quot;:872,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:71401,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!lA1R!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5d64b1f-f1ea-4e7a-9750-ab37b0e72393_872x842.png 424w, https://substackcdn.com/image/fetch/$s_!lA1R!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5d64b1f-f1ea-4e7a-9750-ab37b0e72393_872x842.png 848w, https://substackcdn.com/image/fetch/$s_!lA1R!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5d64b1f-f1ea-4e7a-9750-ab37b0e72393_872x842.png 1272w, https://substackcdn.com/image/fetch/$s_!lA1R!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5d64b1f-f1ea-4e7a-9750-ab37b0e72393_872x842.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>Why External System Contract Tests?</h2><p>Within <a href="https://journal.optivem.com/p/acceptance-tests">Acceptance Tests</a>, we&#8217;d seen how E2E Tests are limited because they can only test some Acceptance Criteria, whereas Acceptance Tests are able to test all the Acceptance Criteria.</p><p>So, can we just replace the E2E Tests with Acceptance Tests?</p><p>This would be problematic for the following reason: &#11015;&#65039;&#11015;&#65039;&#11015;&#65039;</p>
      <p>
          <a href="https://journal.optivem.com/p/external-system-contract-tests">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[TDD in Legacy Code - External System Contract Tests]]></title><description><![CDATA[Acceptance Tests rely on External System Stubs. But how to we know that those Stubs are actually valid? We can only know if we have External System Contract Tests.]]></description><link>https://journal.optivem.com/p/external-system-contract-tests-in-legacy-code</link><guid isPermaLink="false">https://journal.optivem.com/p/external-system-contract-tests-in-legacy-code</guid><dc:creator><![CDATA[Valentina Jemuović]]></dc:creator><pubDate>Fri, 06 Dec 2024 07:02:00 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/782bf19f-e18b-4b0e-ab78-97eb65cb57a2_1000x666.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>&#128274;Hello, this is Valentina with a premium issue of the Optivem Journal. I help Engineering Leaders &amp; Senior Software Developers apply TDD in Legacy Code. This article is part of the <a href="https://journal.optivem.com/p/tdd-in-legacy-code-outline">TDD in Legacy Code</a> series. To get these articles in your inbox every week, subscribe:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://journal.optivem.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://journal.optivem.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2>Acceptance Tests rely on External System Stubs</h2><p>In Acceptance Tests, we stub out External Systems, rather than connecting with the real External Systems, in order to test our System in isolation. By using Stubs, we have full control - we can translate any functional Acceptance Criteria into Acceptance Tests, which is a big benefit compared to E2E Tests.</p><h2>But what if the External System Stubs are wrong?!</h2><p>Suppose that we incorrectly stub out External Systems - perhaps we made an accidental spelling mistake in an endpoint. If that same &#8220;mistake&#8220; is also in our System source code, the Acceptance Test will pass, even though the Stub is wrong!</p><p>The passing Acceptance Test gives us a false sense of security - this is very dangerous!</p><h2>How can we ensure that the Stubs are valid?</h2><p>We need Contract Tests for External Systems which will be executed both against the External System Stubs and against the External System Test Instances.</p><p>I&#8217;ll show you how to add Contract Tests to provide assurance that the External System Stub Drivers are actually valid.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!PZjQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F537f42a9-0083-437c-9836-8658d8e4c23b_4820x1239.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PZjQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F537f42a9-0083-437c-9836-8658d8e4c23b_4820x1239.png 424w, https://substackcdn.com/image/fetch/$s_!PZjQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F537f42a9-0083-437c-9836-8658d8e4c23b_4820x1239.png 848w, https://substackcdn.com/image/fetch/$s_!PZjQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F537f42a9-0083-437c-9836-8658d8e4c23b_4820x1239.png 1272w, https://substackcdn.com/image/fetch/$s_!PZjQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F537f42a9-0083-437c-9836-8658d8e4c23b_4820x1239.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PZjQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F537f42a9-0083-437c-9836-8658d8e4c23b_4820x1239.png" width="1456" height="374" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/537f42a9-0083-437c-9836-8658d8e4c23b_4820x1239.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:374,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:284423,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!PZjQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F537f42a9-0083-437c-9836-8658d8e4c23b_4820x1239.png 424w, https://substackcdn.com/image/fetch/$s_!PZjQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F537f42a9-0083-437c-9836-8658d8e4c23b_4820x1239.png 848w, https://substackcdn.com/image/fetch/$s_!PZjQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F537f42a9-0083-437c-9836-8658d8e4c23b_4820x1239.png 1272w, https://substackcdn.com/image/fetch/$s_!PZjQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F537f42a9-0083-437c-9836-8658d8e4c23b_4820x1239.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Here are the steps to introduce External System Contract Tests in Legacy Code. I&#8217;ll provide you with step-by-step guidance on how to introduce them in your GitHub Sandbox Project. &#11015;&#65039;&#11015;&#65039;&#11015;&#65039;</p>
      <p>
          <a href="https://journal.optivem.com/p/external-system-contract-tests-in-legacy-code">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[E2E Tests]]></title><description><![CDATA[E2E Tests verify System behavior in the most realistic way, by connecting to External Systems. However, they can cover only limited scenarios, and that's why we'll have few E2E Tests.]]></description><link>https://journal.optivem.com/p/e2e-tests</link><guid isPermaLink="false">https://journal.optivem.com/p/e2e-tests</guid><dc:creator><![CDATA[Valentina Jemuović]]></dc:creator><pubDate>Wed, 20 Nov 2024 07:01:28 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/697240ca-bddc-4528-8108-32e1849215ab_1000x666.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>&#128274;Hello, this is Valentina with a premium issue of the Optivem Journal. I help Engineering Leaders &amp; Senior Software Developers apply TDD in Legacy Code. This article is part of the <a href="https://journal.optivem.com/p/tdd-in-legacy-code-outline">TDD in Legacy Code</a> series. To get these articles in your inbox every week, subscribe:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://journal.optivem.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://journal.optivem.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2>What are E2E Tests?</h2><p>We use E2E Tests to verify System behavior, however the scenarios are limited.</p><p>E2E Tests target the System - they span the System and External System Test Instances. They&#8217;re executed on the E2E Environment.</p><p>E2E Tests are slow. They&#8217;re limited in terms of the scenarios we can execute because we can&#8217;t fully control the External System Test Instances. Furthermore, we can&#8217;t control the System Clock either. Consequently, we&#8217;re very limited regarding scenarios that we can cover with E2E Tests, hence there&#8217;s a lot of Acceptance Criteria that we can&#8217;t even test with E2E Tests - but we can test it with Acceptance Tests.</p><p><em>The difference between E2E Tests and Smoke Tests is that when connecting to the External Systems, E2E Tests connect to External System Test Instances, whereas Smoke Tests can connect to either External System Test Instances or External System Stubs (depending on which environment they&#8217;re run on). Also, E2E Tests cover the critical Use Cases, to the extent that certain scenarios are possible.</em></p><div><hr></div><p>If the System exposes a UI (for End Users), the E2E Test can use a Web Driver to run commands on the UI, and to do verifications via the UI:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ne1O!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6308ee51-4cc4-458f-98aa-2b765ac64554_1060x599.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ne1O!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6308ee51-4cc4-458f-98aa-2b765ac64554_1060x599.png 424w, https://substackcdn.com/image/fetch/$s_!Ne1O!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6308ee51-4cc4-458f-98aa-2b765ac64554_1060x599.png 848w, https://substackcdn.com/image/fetch/$s_!Ne1O!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6308ee51-4cc4-458f-98aa-2b765ac64554_1060x599.png 1272w, https://substackcdn.com/image/fetch/$s_!Ne1O!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6308ee51-4cc4-458f-98aa-2b765ac64554_1060x599.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ne1O!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6308ee51-4cc4-458f-98aa-2b765ac64554_1060x599.png" width="1060" height="599" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6308ee51-4cc4-458f-98aa-2b765ac64554_1060x599.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:599,&quot;width&quot;:1060,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:48454,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Ne1O!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6308ee51-4cc4-458f-98aa-2b765ac64554_1060x599.png 424w, https://substackcdn.com/image/fetch/$s_!Ne1O!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6308ee51-4cc4-458f-98aa-2b765ac64554_1060x599.png 848w, https://substackcdn.com/image/fetch/$s_!Ne1O!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6308ee51-4cc4-458f-98aa-2b765ac64554_1060x599.png 1272w, https://substackcdn.com/image/fetch/$s_!Ne1O!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6308ee51-4cc4-458f-98aa-2b765ac64554_1060x599.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><p>If the System exposes a REST API (so that other systems can connect to it), the E2E Test can use a HTTP Client to connect to the System&#8217;s REST API, and do verifications via the REST API:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FFj4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa245757e-f28c-40b7-ad41-aad2e673f7e3_1060x599.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FFj4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa245757e-f28c-40b7-ad41-aad2e673f7e3_1060x599.png 424w, https://substackcdn.com/image/fetch/$s_!FFj4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa245757e-f28c-40b7-ad41-aad2e673f7e3_1060x599.png 848w, https://substackcdn.com/image/fetch/$s_!FFj4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa245757e-f28c-40b7-ad41-aad2e673f7e3_1060x599.png 1272w, https://substackcdn.com/image/fetch/$s_!FFj4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa245757e-f28c-40b7-ad41-aad2e673f7e3_1060x599.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!FFj4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa245757e-f28c-40b7-ad41-aad2e673f7e3_1060x599.png" width="1060" height="599" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a245757e-f28c-40b7-ad41-aad2e673f7e3_1060x599.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:599,&quot;width&quot;:1060,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:50637,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!FFj4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa245757e-f28c-40b7-ad41-aad2e673f7e3_1060x599.png 424w, https://substackcdn.com/image/fetch/$s_!FFj4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa245757e-f28c-40b7-ad41-aad2e673f7e3_1060x599.png 848w, https://substackcdn.com/image/fetch/$s_!FFj4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa245757e-f28c-40b7-ad41-aad2e673f7e3_1060x599.png 1272w, https://substackcdn.com/image/fetch/$s_!FFj4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa245757e-f28c-40b7-ad41-aad2e673f7e3_1060x599.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><p>If the System exposes both a UI and a REST API, then we combine the above:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1rGR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F416b64b7-13ed-4619-9135-01c31308b6be_1060x609.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1rGR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F416b64b7-13ed-4619-9135-01c31308b6be_1060x609.png 424w, https://substackcdn.com/image/fetch/$s_!1rGR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F416b64b7-13ed-4619-9135-01c31308b6be_1060x609.png 848w, https://substackcdn.com/image/fetch/$s_!1rGR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F416b64b7-13ed-4619-9135-01c31308b6be_1060x609.png 1272w, https://substackcdn.com/image/fetch/$s_!1rGR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F416b64b7-13ed-4619-9135-01c31308b6be_1060x609.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1rGR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F416b64b7-13ed-4619-9135-01c31308b6be_1060x609.png" width="1060" height="609" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/416b64b7-13ed-4619-9135-01c31308b6be_1060x609.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:609,&quot;width&quot;:1060,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:55939,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1rGR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F416b64b7-13ed-4619-9135-01c31308b6be_1060x609.png 424w, https://substackcdn.com/image/fetch/$s_!1rGR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F416b64b7-13ed-4619-9135-01c31308b6be_1060x609.png 848w, https://substackcdn.com/image/fetch/$s_!1rGR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F416b64b7-13ed-4619-9135-01c31308b6be_1060x609.png 1272w, https://substackcdn.com/image/fetch/$s_!1rGR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F416b64b7-13ed-4619-9135-01c31308b6be_1060x609.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><h2>Why E2E Tests?</h2><p>Dave Farley said: &#8220;<a href="https://www.youtube.com/watch?v=P_570bqxDYo">Don&#8217;t Do E2E Testing!</a>&#8220; </p><p>The idea is to replace E2E Tests by Acceptance Tests &amp; External System Contract Tests.</p><p>That makes E2E Tests redundant, right?</p><p>Should we completely eliminate E2E Tests.</p><p>This is problematic for two reasons: &#11015;&#65039;&#11015;&#65039;&#11015;&#65039;</p>
      <p>
          <a href="https://journal.optivem.com/p/e2e-tests">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Smoke Tests]]></title><description><![CDATA[Smoke Tests are help us verify whether the System is up-and-running, that's why they're executed before Acceptance Tests & E2E Tests in the Pipeline.]]></description><link>https://journal.optivem.com/p/smoke-tests</link><guid isPermaLink="false">https://journal.optivem.com/p/smoke-tests</guid><dc:creator><![CDATA[Valentina Jemuović]]></dc:creator><pubDate>Wed, 13 Nov 2024 06:50:42 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/361eb35d-03bd-4813-9dd1-a82ca20c0bdb_1000x666.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>&#128274;Hello, this is Valentina with a premium issue of the Optivem Journal. I help Engineering Leaders &amp; Senior Software Developers apply TDD in Legacy Code. This article is part of the <a href="https://journal.optivem.com/p/tdd-in-legacy-code-outline">TDD in Legacy Code</a> series. To get these articles in your inbox every week, subscribe:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://journal.optivem.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://journal.optivem.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2>What are Smoke Tests?</h2><p>We use Smoke Tests to verify that the System is up-and-running.</p><p>Smoke Tests target the System - they span the System and External System Stubs or External System Test Instances. </p><ul><li><p>Smoke Tests executed on the Acceptance Environment span the External System Stubs. </p></li><li><p>Smoke Tests executed on the E2E Environment span External System Test Instances. </p></li></ul><p>Smoke Tests are executed before Acceptance Tests &amp; E2E Tests because they provide feedback. It makes sense to execute Acceptance Tests &amp; E2E Tests only after Smoke Tests pass.</p><p><em>Smoke Tests are similar to E2E Tests in terms of span. The difference is that there are very few Smoke Tests, and they don&#8217;t test Use Cases, but rather basics such as whether the main page has loaded, whether login works, etc. They quickly verify that the System is up-and-running after deployment. After the Smoke Tests pass, we&#8217;re ready to run other System Level Tests (E2E Tests, Acceptance Tests, External System Contract Tests).</em></p><div><hr></div><p>If the System exposes a UI (for End Users), the Smoke Test can use a Web Driver to run commands on the UI, and to do verifications via the UI:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iYkW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e13dd93-3384-49b8-8eaf-4f0e9e43dd7c_1060x599.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iYkW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e13dd93-3384-49b8-8eaf-4f0e9e43dd7c_1060x599.png 424w, https://substackcdn.com/image/fetch/$s_!iYkW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e13dd93-3384-49b8-8eaf-4f0e9e43dd7c_1060x599.png 848w, https://substackcdn.com/image/fetch/$s_!iYkW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e13dd93-3384-49b8-8eaf-4f0e9e43dd7c_1060x599.png 1272w, https://substackcdn.com/image/fetch/$s_!iYkW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e13dd93-3384-49b8-8eaf-4f0e9e43dd7c_1060x599.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iYkW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e13dd93-3384-49b8-8eaf-4f0e9e43dd7c_1060x599.png" width="1060" height="599" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8e13dd93-3384-49b8-8eaf-4f0e9e43dd7c_1060x599.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:599,&quot;width&quot;:1060,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:52721,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!iYkW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e13dd93-3384-49b8-8eaf-4f0e9e43dd7c_1060x599.png 424w, https://substackcdn.com/image/fetch/$s_!iYkW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e13dd93-3384-49b8-8eaf-4f0e9e43dd7c_1060x599.png 848w, https://substackcdn.com/image/fetch/$s_!iYkW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e13dd93-3384-49b8-8eaf-4f0e9e43dd7c_1060x599.png 1272w, https://substackcdn.com/image/fetch/$s_!iYkW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e13dd93-3384-49b8-8eaf-4f0e9e43dd7c_1060x599.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><p>If the System exposes a REST API (so that other systems can connect to it), the Smoke Test can use a HTTP Client to connect to the System&#8217;s REST API, and do verifications via the REST API:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!17U7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdc933b8-2068-425c-bcd4-60b2a3a6355d_1060x599.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!17U7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdc933b8-2068-425c-bcd4-60b2a3a6355d_1060x599.png 424w, https://substackcdn.com/image/fetch/$s_!17U7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdc933b8-2068-425c-bcd4-60b2a3a6355d_1060x599.png 848w, https://substackcdn.com/image/fetch/$s_!17U7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdc933b8-2068-425c-bcd4-60b2a3a6355d_1060x599.png 1272w, https://substackcdn.com/image/fetch/$s_!17U7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdc933b8-2068-425c-bcd4-60b2a3a6355d_1060x599.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!17U7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdc933b8-2068-425c-bcd4-60b2a3a6355d_1060x599.png" width="1060" height="599" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cdc933b8-2068-425c-bcd4-60b2a3a6355d_1060x599.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:599,&quot;width&quot;:1060,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:54895,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!17U7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdc933b8-2068-425c-bcd4-60b2a3a6355d_1060x599.png 424w, https://substackcdn.com/image/fetch/$s_!17U7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdc933b8-2068-425c-bcd4-60b2a3a6355d_1060x599.png 848w, https://substackcdn.com/image/fetch/$s_!17U7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdc933b8-2068-425c-bcd4-60b2a3a6355d_1060x599.png 1272w, https://substackcdn.com/image/fetch/$s_!17U7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdc933b8-2068-425c-bcd4-60b2a3a6355d_1060x599.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><p>If the System exposes both a UI and a REST API, then we combine the above:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jG96!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3873d539-da66-4706-b5ef-846c3ca683eb_1060x609.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jG96!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3873d539-da66-4706-b5ef-846c3ca683eb_1060x609.png 424w, https://substackcdn.com/image/fetch/$s_!jG96!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3873d539-da66-4706-b5ef-846c3ca683eb_1060x609.png 848w, https://substackcdn.com/image/fetch/$s_!jG96!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3873d539-da66-4706-b5ef-846c3ca683eb_1060x609.png 1272w, https://substackcdn.com/image/fetch/$s_!jG96!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3873d539-da66-4706-b5ef-846c3ca683eb_1060x609.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jG96!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3873d539-da66-4706-b5ef-846c3ca683eb_1060x609.png" width="1060" height="609" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3873d539-da66-4706-b5ef-846c3ca683eb_1060x609.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:609,&quot;width&quot;:1060,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:60716,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!jG96!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3873d539-da66-4706-b5ef-846c3ca683eb_1060x609.png 424w, https://substackcdn.com/image/fetch/$s_!jG96!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3873d539-da66-4706-b5ef-846c3ca683eb_1060x609.png 848w, https://substackcdn.com/image/fetch/$s_!jG96!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3873d539-da66-4706-b5ef-846c3ca683eb_1060x609.png 1272w, https://substackcdn.com/image/fetch/$s_!jG96!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3873d539-da66-4706-b5ef-846c3ca683eb_1060x609.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><h2>Why Smoke Tests?</h2><p>Suppose we just had E2E Tests (or Acceptance Tests), but didn&#8217;t have any Smoke Tests.</p><p>We run E2E Tests (or Acceptance Tests). The tests start failing. Then we start debugging, and find out it&#8217;s because deployment failed, or there&#8217;s some web server configuration error preventing us from accessing the system, or the External System Test Instances (or their Stubs) are not running, etc.</p><p>This is problematic for two reasons: &#11015;&#65039;&#11015;&#65039;&#11015;&#65039;</p>
      <p>
          <a href="https://journal.optivem.com/p/smoke-tests">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[TDD in Legacy Code - Maintainable E2E Tests]]></title><description><![CDATA[E2E Tests are often coupled to the UI, many tests can easily break due to minor visual changes. This makes them very expensive to maintain. We need to refactor them with Layered Model.]]></description><link>https://journal.optivem.com/p/maintainable-e2e-tests-in-legacy-code</link><guid isPermaLink="false">https://journal.optivem.com/p/maintainable-e2e-tests-in-legacy-code</guid><dc:creator><![CDATA[Valentina Jemuović]]></dc:creator><pubDate>Thu, 07 Nov 2024 15:08:07 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/fa5c23a7-5bcc-4b32-a5c4-fc677b7737ba_1000x666.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>&#128274;Hello, this is Valentina with a premium issue of the Optivem Journal. I help Engineering Leaders &amp; Senior Software Developers apply TDD in Legacy Code. This article is part of the <a href="https://journal.optivem.com/p/tdd-in-legacy-code-outline">TDD in Legacy Code</a> series. To get these articles in your inbox every week, subscribe:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://journal.optivem.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://journal.optivem.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2>Legacy Code often has E2E Tests coupled to the UI</h2><p>When we introduced E2E Tests into Legacy Code, we wrote the tests directly using a WebDriver, and then redesigned them to use the Page Object Model.</p><h2>These E2E Tests are hard to maintain</h2><p>In both cases, the tests are hard to maintain - in the POM Model, the tests are directly coupled to the UI structure.</p><h2>We need to adopt a maintainable E2E Design</h2><p>Let&#8217;s see how to introduce maintainability and make the E2E Tests more readable and decoupled from the System implementation. Even as the System API changes (due to UI changes and public REST API changes), if the behavior doesn&#8217;t change, our tests remain stable and only a small percentage of plumbing is affected:</p><p>Previously, we introduced:</p><ul><li><p>E2E Tests - WebDriver Model</p></li><li><p>E2E Tests - POM Model</p></li></ul><p>Now let&#8217;s refactor towards:</p><ul><li><p>E2E Tests - DSL-POM Model</p></li><li><p>E2E Tests - Four Layer Model</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nvdB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b52565e-778b-406a-bb74-713f35e7e441_4820x1239.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nvdB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b52565e-778b-406a-bb74-713f35e7e441_4820x1239.png 424w, https://substackcdn.com/image/fetch/$s_!nvdB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b52565e-778b-406a-bb74-713f35e7e441_4820x1239.png 848w, https://substackcdn.com/image/fetch/$s_!nvdB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b52565e-778b-406a-bb74-713f35e7e441_4820x1239.png 1272w, https://substackcdn.com/image/fetch/$s_!nvdB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b52565e-778b-406a-bb74-713f35e7e441_4820x1239.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nvdB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b52565e-778b-406a-bb74-713f35e7e441_4820x1239.png" width="1456" height="374" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3b52565e-778b-406a-bb74-713f35e7e441_4820x1239.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:374,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:284305,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!nvdB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b52565e-778b-406a-bb74-713f35e7e441_4820x1239.png 424w, https://substackcdn.com/image/fetch/$s_!nvdB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b52565e-778b-406a-bb74-713f35e7e441_4820x1239.png 848w, https://substackcdn.com/image/fetch/$s_!nvdB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b52565e-778b-406a-bb74-713f35e7e441_4820x1239.png 1272w, https://substackcdn.com/image/fetch/$s_!nvdB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b52565e-778b-406a-bb74-713f35e7e441_4820x1239.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Here are the steps for refactoring E2E Tests in Legacy Code. You&#8217;ll get tasks to implement in your GitHub Sandbox Project. &#11015;&#65039;&#11015;&#65039;&#11015;&#65039;</p>
      <p>
          <a href="https://journal.optivem.com/p/maintainable-e2e-tests-in-legacy-code">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[TDD in Legacy Code - E2E Testable Architecture]]></title><description><![CDATA[Legacy Code might be so tangled up that it might not even be E2E Testable, which prevents us from introducing E2E Tests and Acceptance Tests. We need an E2E Testable Architecture.]]></description><link>https://journal.optivem.com/p/e2e-testable-architecture-in-legacy-code</link><guid isPermaLink="false">https://journal.optivem.com/p/e2e-testable-architecture-in-legacy-code</guid><dc:creator><![CDATA[Valentina Jemuović]]></dc:creator><pubDate>Fri, 01 Nov 2024 12:08:55 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/fddb13d5-219e-4567-8ed4-7d35e03a09c0_1000x666.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>&#128274;Hello, this is Valentina with a premium issue of the Optivem Journal. I help Engineering Leaders &amp; Senior Software Developers apply TDD in Legacy Code. This article is part of the <a href="https://journal.optivem.com/p/tdd-in-legacy-code-outline">TDD in Legacy Code</a> series. To get these articles in your inbox every week, subscribe:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://journal.optivem.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://journal.optivem.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2>Legacy Code might not be E2E Testable</h2><p>Legacy projects might have the following problems:</p><ul><li><p>Hard-coded connection strings to Production Instances of External Systems &#8594; this is dangerous because we can change the state of Production Instances during testing</p></li><li><p>External Systems might still be in development &#8594; we might need to wait months for months for the External Team to release a Test Instance so that we can test our integration with them</p></li></ul><h2>Then we can&#8217;t introduce automated E2E Tests</h2><p>In those cases, we can&#8217;t introduce E2E Tests at all, because we want to be able to run E2E Tests safely, at any time, no constraints, and independently of the development status of other teams. <em>(This problem applies not only to E2E tests, but also to Smoke Tests)</em></p><h2>We need to ensure E2E Testable Architecture</h2><p>Often developers try to introduce just Unit Testability (a lot of techniques in <a href="https://www.amazon.com/Working-Effectively-Legacy-Code-EFFECT-ebook/dp/B005OYHF0A">Working Effectively with Legacy Code</a> help you untangle messy code to make it Unit Testable).</p><p>The problem is, based on my experience, it&#8217;s too much to try to jump to Unit Testability. That&#8217;s why I start with E2E Testable Architecture, then Acceptance Testable Architecture, then Component Testable Architecture, and finally, last but not least, to Unit Testable Architecture.</p><p>Is your architecture E2E Testable? If not, you need to re-architect it to support testability.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!g-Mr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8890855c-c8bd-4ccc-becd-90aea9b2a288_4820x1239.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!g-Mr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8890855c-c8bd-4ccc-becd-90aea9b2a288_4820x1239.png 424w, https://substackcdn.com/image/fetch/$s_!g-Mr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8890855c-c8bd-4ccc-becd-90aea9b2a288_4820x1239.png 848w, https://substackcdn.com/image/fetch/$s_!g-Mr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8890855c-c8bd-4ccc-becd-90aea9b2a288_4820x1239.png 1272w, https://substackcdn.com/image/fetch/$s_!g-Mr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8890855c-c8bd-4ccc-becd-90aea9b2a288_4820x1239.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!g-Mr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8890855c-c8bd-4ccc-becd-90aea9b2a288_4820x1239.png" width="1456" height="374" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8890855c-c8bd-4ccc-becd-90aea9b2a288_4820x1239.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:374,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:280707,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!g-Mr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8890855c-c8bd-4ccc-becd-90aea9b2a288_4820x1239.png 424w, https://substackcdn.com/image/fetch/$s_!g-Mr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8890855c-c8bd-4ccc-becd-90aea9b2a288_4820x1239.png 848w, https://substackcdn.com/image/fetch/$s_!g-Mr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8890855c-c8bd-4ccc-becd-90aea9b2a288_4820x1239.png 1272w, https://substackcdn.com/image/fetch/$s_!g-Mr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8890855c-c8bd-4ccc-becd-90aea9b2a288_4820x1239.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Here are the steps for achieving E2E Testable Architecture in Legacy Code. You&#8217;ll get tasks to implement in your GitHub Sandbox Project. &#11015;&#65039;&#11015;&#65039;&#11015;&#65039;</p>
      <p>
          <a href="https://journal.optivem.com/p/e2e-testable-architecture-in-legacy-code">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[TDD in Legacy Code - E2E Tests]]></title><description><![CDATA[In Legacy Code, E2E Tests are often performed manually. This makes it inconvenient to jump to introducing Acceptance Tests. Let's see how we can introduce automated E2E tests as a preparatory step.]]></description><link>https://journal.optivem.com/p/e2e-tests-in-legacy-code</link><guid isPermaLink="false">https://journal.optivem.com/p/e2e-tests-in-legacy-code</guid><dc:creator><![CDATA[Valentina Jemuović]]></dc:creator><pubDate>Thu, 24 Oct 2024 06:00:51 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/ce09b338-f3dd-4a65-959c-3d2e0fb0f31e_1000x666.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>&#128274;Hello, this is Valentina with a premium issue of the Optivem Journal. I help Engineering Leaders &amp; Senior Software Developers apply TDD in Legacy Code. This article is part of the <a href="https://journal.optivem.com/p/tdd-in-legacy-code-outline">TDD in Legacy Code</a> series. To get these articles in your inbox every week, subscribe:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://journal.optivem.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://journal.optivem.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2>Legacy Code has Manual E2E Testing</h2><p>In Legacy Projects, QA Engineers often perform manual E2E tests based on written test procedures.</p><h2>Hard to jump to ATDD with Manual E2E Tests</h2><p>Like E2E Tests, Acceptance Tests test the functionality from the End User perspective (except that Acceptance Tests use External System Stubs rather than External System Test Instances).</p><p>It&#8217;s very hard to jump straight into writing Acceptance Tests retroactively when there aren&#8217;t even any automated E2E tests in place.</p><h2>Convenient to automate E2E Tests before ATDD</h2><p>It&#8217;s convenient to start with automated E2E Tests, and then transition to Acceptance Tests, by swapping out the External System Test Instances with External System Stubs).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!f2jS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd48e1115-b3cd-4a01-a8cd-a1db07187946_4820x1239.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!f2jS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd48e1115-b3cd-4a01-a8cd-a1db07187946_4820x1239.png 424w, https://substackcdn.com/image/fetch/$s_!f2jS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd48e1115-b3cd-4a01-a8cd-a1db07187946_4820x1239.png 848w, https://substackcdn.com/image/fetch/$s_!f2jS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd48e1115-b3cd-4a01-a8cd-a1db07187946_4820x1239.png 1272w, https://substackcdn.com/image/fetch/$s_!f2jS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd48e1115-b3cd-4a01-a8cd-a1db07187946_4820x1239.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!f2jS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd48e1115-b3cd-4a01-a8cd-a1db07187946_4820x1239.png" width="1456" height="374" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d48e1115-b3cd-4a01-a8cd-a1db07187946_4820x1239.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:374,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:283970,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!f2jS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd48e1115-b3cd-4a01-a8cd-a1db07187946_4820x1239.png 424w, https://substackcdn.com/image/fetch/$s_!f2jS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd48e1115-b3cd-4a01-a8cd-a1db07187946_4820x1239.png 848w, https://substackcdn.com/image/fetch/$s_!f2jS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd48e1115-b3cd-4a01-a8cd-a1db07187946_4820x1239.png 1272w, https://substackcdn.com/image/fetch/$s_!f2jS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd48e1115-b3cd-4a01-a8cd-a1db07187946_4820x1239.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Here are the steps for writing E2E Tests in Legacy Code. You&#8217;ll get tasks to implement in your GitHub Sandbox Project. &#11015;&#65039;&#11015;&#65039;&#11015;&#65039;</p>
      <p>
          <a href="https://journal.optivem.com/p/e2e-tests-in-legacy-code">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[TDD in Legacy Code - Smoke Tests]]></title><description><![CDATA[In Legacy Code, Smoke Testing is often done manually, which makes ATDD impractical. Let's see how we can introduce automated Smoke Testing as an enabler for ATDD.]]></description><link>https://journal.optivem.com/p/smoke-tests-in-legacy-code</link><guid isPermaLink="false">https://journal.optivem.com/p/smoke-tests-in-legacy-code</guid><dc:creator><![CDATA[Valentina Jemuović]]></dc:creator><pubDate>Thu, 17 Oct 2024 06:01:14 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/88f68675-d0a0-407e-8995-cf984ffffe0c_1000x666.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>&#128274;Hello, this is Valentina with a premium issue of the Optivem Journal. I help Engineering Leaders &amp; Senior Software Developers apply TDD in Legacy Code. This article is part of the <a href="https://journal.optivem.com/p/tdd-in-legacy-code-outline">TDD in Legacy Code</a> series. To get these articles in your inbox every week, subscribe:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://journal.optivem.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://journal.optivem.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2>Legacy Code has Manual Smoke Tests</h2><p>In Legacy Code, it is typical that when the system is deployed to the UAT Environment, the QA Engineer might carry out a basic smoke test to ensure that the system is up-and-running, before they proceed to perform manual E2E tests. </p><p>An example of a basic end-user facing smoke test might be to open up the main page in the browser, and check that the page has loaded. The QA Engineer might also perform manual smoke testing for the backend, such as running some health check endpoint, checking if the database is running, checking whether the message broker is up and running - by manually trying to connect to the database server, manually connecting to administrative page of the message broker.</p><p>Then, when they see that the Manual Smoke Tests are passing, they can perform Manual E2E Testing.</p><h2>We can&#8217;t do ATDD with Manual Smoke Tests</h2><p>Since we want to adopt ATDD, we&#8217;d need to ensure that our system is up and running after it&#8217;s released before running the Acceptance Tests. The reason is that if the Smoke Tests fail, then it doesn&#8217;t make sense to run the Acceptance Tests. Since we&#8217;d want to be able to run Acceptance Tests regularly throughout the day, it&#8217;s infeasible to run manual Smoke Tests before running automated Acceptance Tests.</p><h2>We need automated Smoke Tests for ATDD</h2><p>That&#8217;s why we need Smoke Tests to be automated, so that we can immediately run them after deploying to any environment. Thus, after releasing the system to the Acceptance Environment, we could run Smoke Tests, and then Acceptance Tests.</p><p><em>Previously, we&#8217;d set up the <a href="https://journal.optivem.com/p/pipeline-in-legacy-code">Pipeline</a> - we set up the Smoke Testing step within the Pipeline, but at that point, the tests were just placeholders. In this article, we&#8217;ll be writing the actual tests.</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!zlxx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52667d59-b29c-4655-821f-396a7fec61ce_4820x1239.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!zlxx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52667d59-b29c-4655-821f-396a7fec61ce_4820x1239.png 424w, https://substackcdn.com/image/fetch/$s_!zlxx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52667d59-b29c-4655-821f-396a7fec61ce_4820x1239.png 848w, https://substackcdn.com/image/fetch/$s_!zlxx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52667d59-b29c-4655-821f-396a7fec61ce_4820x1239.png 1272w, https://substackcdn.com/image/fetch/$s_!zlxx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52667d59-b29c-4655-821f-396a7fec61ce_4820x1239.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!zlxx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52667d59-b29c-4655-821f-396a7fec61ce_4820x1239.png" width="1456" height="374" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/52667d59-b29c-4655-821f-396a7fec61ce_4820x1239.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:374,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:283897,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!zlxx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52667d59-b29c-4655-821f-396a7fec61ce_4820x1239.png 424w, https://substackcdn.com/image/fetch/$s_!zlxx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52667d59-b29c-4655-821f-396a7fec61ce_4820x1239.png 848w, https://substackcdn.com/image/fetch/$s_!zlxx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52667d59-b29c-4655-821f-396a7fec61ce_4820x1239.png 1272w, https://substackcdn.com/image/fetch/$s_!zlxx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52667d59-b29c-4655-821f-396a7fec61ce_4820x1239.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Here are the steps for writing Smoke Tests for Legacy Code. You&#8217;ll get tasks to implement in your GitHub Sandbox Project. &#11015;&#65039;&#11015;&#65039;&#11015;&#65039;</p>
      <p>
          <a href="https://journal.optivem.com/p/smoke-tests-in-legacy-code">
              Read more
          </a>
      </p>
   ]]></content:encoded></item></channel></rss>