<?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:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Sotiropoulos Georgios on Medium]]></title>
        <description><![CDATA[Stories by Sotiropoulos Georgios on Medium]]></description>
        <link>https://medium.com/@ge.sotiropoulos?source=rss-f1e944862e90------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/2*m2pOrcN8fj2bB7F206vsSA.jpeg</url>
            <title>Stories by Sotiropoulos Georgios on Medium</title>
            <link>https://medium.com/@ge.sotiropoulos?source=rss-f1e944862e90------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Tue, 03 Nov 2026 06:31:25 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@ge.sotiropoulos/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Shifting UI tests to the far left (part 2)]]></title>
            <link>https://medium.com/@ge.sotiropoulos/shifting-ui-tests-to-the-far-left-part-2-a8a5c8b71df1?source=rss-f1e944862e90------2</link>
            <guid isPermaLink="false">https://medium.com/p/a8a5c8b71df1</guid>
            <category><![CDATA[ui-test-automation]]></category>
            <category><![CDATA[qa]]></category>
            <category><![CDATA[specifications]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[ui-testing]]></category>
            <dc:creator><![CDATA[Sotiropoulos Georgios]]></dc:creator>
            <pubDate>Wed, 10 Apr 2024 09:10:29 GMT</pubDate>
            <atom:updated>2024-04-10T09:23:23.838Z</atom:updated>
            <content:encoded><![CDATA[<h4>How you write specifications using UI tests before the development even starts</h4><p>In the <a href="https://medium.com/@ge.sotiropoulos/shifting-ui-tests-to-the-far-left-6784f798acc2"><strong>first part of the article</strong></a>, we established not only that UI tests can be used to write specifications for mobile apps, but that they can also be very expressive in doing so, allowing for accurate modelling of the behaviour of the system and leaving no room for overlooked specifications.</p><p>If you were though to use UI tests to write specifications, then you would also need to have a way to do so before the development even starts while still in the specifications phase. Let’s see how we can do this.</p><p>Before embracing the “UI tests as specifications” approach, the timeline of a feature release in our team, from the requirements phase to the actual release looked like that.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_ag0-t5VVWo6mWe1nD6G5g.png" /><figcaption>Writing UI tests at the end of the development phase</figcaption></figure><p>The product team outlined requirements, which business analysts refined through discussions with developers and stakeholders. They clarified designs, created documentation, and incorporated BDD scenarios. Development prioritised unit and snapshot testing, with UI tests addressed at the end, based on team availability.</p><p>UI tests were essentially a 2nd class citizen due to time constraints and maintenance challenges. With the goal of turning them to a <strong>1st class citizen</strong> we shifted them to the far left, becoming part of the specifications phase and replacing the BDD scenarios.</p><figure><img alt="Shifting UI tests to the far left, to the specifications phase replacing the BDD scenarios and writing them before the development even starts" src="https://cdn-images-1.medium.com/max/1024/1*9jKbOe1R7E7TWgmqdYRYrw.png" /><figcaption>Writing UI tests as specifications before the development even starts</figcaption></figure><p>Writing UI tests becomes now the responsibility of the feature’s tech lead, who should have the necessary Android and iOS skills to write them. This shift eliminates reliance on developer availability, as the UI tests are now written before the development begins. <strong>Specifications now become acceptance criteria and regression tests at the same time</strong>, making it easier to sync the implementations between Android and iOS.</p><h4><strong>Open the specs MR</strong></h4><p>Before any development starts — remember we are still in the specifications phase trying to write the specifications for our engineers — the feature’s tech lead opens the very 1st MR writing the specs of the feature as UI tests in either iOS or Android.</p><h4>Apply code ownership</h4><p>The specs MR contains only the the UI tests files themselves, all placed within the a folder that is under the code ownership of the feature’s tech lead.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_saDfNGRhA3M7IwwPAn1oQ.jpeg" /></figure><p>And this is quite important because if ever the behaviour of the app was to deviate from the initial specs due to a code change, then the relevant UI tests would fail and we would have to update them. And these updates would need to be approved by the code owner, effectively the owner of the specs themselves, making him aware of any change in the specifications and mismatches between specification and implementation for free.</p><p>And with source control you even have a history of these changes to reason about if needed. <strong>The need to communicate to be in sync about any changes in specs vanishes into thin air 💨</strong>.</p><p>And then the feature’s tech lead starts writing the actual scenarios.</p><h4>Define the preconditions (<strong>network stubs and feature flags)</strong></h4><p>We should start each scenario by leaving a note to the developer what should its preconditions be (<strong>the network stubs</strong>¹ of the API calls that we care about and any <strong>feature flag</strong> setup that you might have). In the scenario we described in part 1 of the article, we specifically care about the two login API calls and we require them to return successfully. All other calls are irrelevant (and are stubbed successfully by default by the way).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1015/1*EdS0CXIWcmgHchTy9hgczA.png" /></figure><p>When writing specs you do not have to implement the stubs — the developer will. You just have to make it explicit for him in the comments section like above.</p><p>Likewise, in non-happy path scenarios, you should make it clear in the comments which API call fails and the relevant error code.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ip-FxlY7d1A9BNoTq_QOtw.png" /></figure><h4>Write the scenario using the Page Object pattern</h4><p>Then you can begin writing the scenario itself using the Page Object pattern which, <a href="https://medium.com/@ge.sotiropoulos/shifting-ui-tests-to-the-far-left-6784f798acc2#6da0">as we have seen</a>, is very close to the clarity of the natural language used in a BDD scenario.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jRcKRupAtL1y25O32osf5A.png" /></figure><h4>Use empty stub methods</h4><p>The methods that we define for each screen (like the LoginScreen in the above example) should be <strong>empty stub methods</strong>. And by empty I mean that you do not care if the <em>tapLoginButton</em> method is actually implemented. The developer will have to implement it when he starts working on this feature, trying to make the test pass. In a TDD fashion but with UI tests if I may say².</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FTfjEYtMPt2E3G78ue6qHg.png" /></figure><h4>Do not leave your API calls unspecified (optional)</h4><p>If you wanted to specify which API calls should be part of this scenario and in what order, you can add them by defining how the snapshot of the API call interaction should look like <a href="https://medium.com/@ge.sotiropoulos/shifting-ui-tests-to-the-far-left-6784f798acc2#5b91">as we saw in part 1 of the article</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RQ8-Hj-g7dGBJxsA7OlwYw.png" /><figcaption>The scenario completed with the API calls also specified</figcaption></figure><h4>Address any question raised during MR code review</h4><p>Writing specs that way we use a language the devs completely understand. In the tool they are most familiar with. When all scenarios are done, you can proceed with requesting feedback on the scenarios and the specs, just like when requesting feedback for a code review.</p><p>When all the discussions are resolved, the specs MR is merged and the development can start. Eventually, the developers will have to make all the tests pass, thus making sure specs are respected.</p><h4>Copy the UI tests for Android as well</h4><p>And in the native mobile development world where the duality between Android and iOS is omnipresent , <strong>syncing the Android implementation becomes as easy as copying the UI tests for Android and applying the same code ownership rules</strong> 🎉🎉.</p><p>It should be clear by now that writing specifications using UI tests before coding <strong>greatly reduces any communication flaws</strong> in the specifications phase, <a href="https://medium.com/@ge.sotiropoulos/shifting-ui-tests-to-the-far-left-6784f798acc2#6d0f"><strong><em>the first most important problems when writing specifications</em></strong></a>. The main benefits include:</p><ul><li>Leaves no ambiguity to the developers</li><li>Specs that never go out of sync with the implementation</li><li>Under source control and code ownership, we can keep track when a requirement is changed</li></ul><p>No more <em>“Oh I have to update the BDD scenarios”</em> or <em>“Is this specification scenario written here still valid? Who should I ask?”</em> or <em>“Does it behave the same in Android and iOS”</em> moments. And then hope that actual implementation in both Android and iOS also follows the specification in question.</p><p><strong>As a project lead, opt for specifications as acceptance criteria and regression tests at the same time, opt for peace of mind</strong> 🧘</p><p><strong>P.S. If you wish to dig more into this exciting topic, you could register for the amazing </strong><a href="https://swiftcraft.uk"><strong>Swift Craft conference</strong></a><strong> (in Southern England between 21–24 of May), where I will be holding a 3 hour workshop on this matter on the 22nd of May.</strong></p><h3>References — Further reading</h3><p>[1] Using network stubs and not the actual network gives us control of the responses and also eliminates the delay and flakiness introduced by the real network.</p><p>[2] People also refer to this as <a href="https://en.wikipedia.org/wiki/Acceptance_test-driven_development">ATDD</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a8a5c8b71df1" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Shifting UI tests to the far left (part 1)]]></title>
            <link>https://medium.com/xmglobal/shifting-ui-tests-to-the-far-left-6784f798acc2?source=rss-f1e944862e90------2</link>
            <guid isPermaLink="false">https://medium.com/p/6784f798acc2</guid>
            <dc:creator><![CDATA[Sotiropoulos Georgios]]></dc:creator>
            <pubDate>Sat, 16 Mar 2024 11:11:28 GMT</pubDate>
            <atom:updated>2024-05-21T07:35:04.134Z</atom:updated>
            <content:encoded><![CDATA[<h4><strong>Can UI tests be used as specifications?</strong></h4><p>Writing specs correctly is a hard thing to do, with <strong>insufficient/hidden specs</strong> and <strong>people communication flaws</strong> being the two most common problems¹. Moreover, people that have led mobile teams know by experience that it is an even harder problem in the native mobile world due to its duality nature, where <strong>engineers from both iOS/Android should understand and implement the exact same thing</strong>.</p><p>Can we remove some of the complexity involved by <strong>writing specs using UI tests</strong> and by <strong>shifting them to the far left at the specification phase</strong> before the development even starts? When can UI tests — or any tests in general — be <strong>considered as specifications</strong> and how can they <strong>reveal behaviours and specs</strong> not manifesting in the UI itself that remain hidden when they shouldn’t? Let’s try to find out.</p><h3>Writing complete and correct specs is a hard thing to do. Why is that?</h3><p>The lifecycle of a feature starts with the <strong>requirements</strong>. Written in natural language by the product team, they provide a description of the required behaviour and they usually live in a Product Requirements Document (PRD²).</p><p>The project tech lead picks up the requirements and transforms them to <strong>specifications</strong>, which are a more technical response to the requirements document. They are used to let the developers know what to build and the testers know what to test.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eigSuSrnudtbLkD4FQ0tcg.png" /><figcaption>From requirements to specifications</figcaption></figure><p>This process often fails, leading to time wasted in back and forth and frustatrion pilling up.</p><h4>People communication flaws</h4><p>Any process that involves people communication over multiple hops has an inherent communication complexity where people have to understand the exact same thing. A process I have seen failing too may times. To make things even worse, in mobile teams the last hop consists of two teams (iOS and Android), an extra complexity that manifests itself in the QA team quite often reporting implementation inconsistencies between the two platforms³.</p><h4>Insufficient/hidden specs</h4><p>Specs are often easy to be missed. Some of them will be discovered or decided only during the implementation phase. For instance, in mobile apps hidden states (loading/error states) are everywhere and often missed in designs. Or the designs themselves say nothing about what happens in the background in terms of API interaction with the backend, leaving room for implementation inconsistencies between Android and iOS to crawl in.</p><p>In the mobile world, UI tests are widespread. If we can demonstrate that they are expressive enough⁴ to effectively capture the various aspects of the mobile app’s behavior, then we could use them to write complete specifications before the implementation even starts, <strong>shifting them to the left to the specifications phase</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2UhwLCCXxCprOrE13I29oQ.gif" /><figcaption>Shift UI tests to the left</figcaption></figure><h4>Acceptance criteria and regression tests at the same</h4><p>Using UI tests to write specifications has the paramount benefit of them also acting as <strong>regression tests</strong>, ensuring that the implementation stays aligned with the specifications and leaving little room for divergence.</p><h3>Under which conditions UI tests can be used as specifications? The 3 conditions</h3><p>To qualify as specifications, UI tests (and all tests in general) must meet three criteria⁵:</p><p><strong>1. They should not change after a refactor</strong></p><p><strong>2. They must be written in a clear, easily understandable format.</strong></p><p><strong>3. They should be expressive enough to uncover any hidden requirements.</strong></p><p>To further explore if UI tests can meet the above conditions and thus be used as specifications, we will use a simple example taken from our application, where we had to migrate to a new backend, requiring when logging in to be authenticated in both old and new backend at the same time during the transition period.</p><p>In this scenario, the <strong>functional requirement</strong> can be expressed in natural language as follows:</p><blockquote>When logging in, we should be authenticated at the same time to the old and the new API, allowing us to access endpoints in both systems.</blockquote><p>And could potentially be further transformed to a <strong>specification</strong> in the following BDD scenario:</p><blockquote><strong>Scenario: User logs in</strong></blockquote><blockquote><strong>Given</strong> that an existing user launches the app</blockquote><blockquote><strong>When</strong> he fills in his credentials in the login page and taps on the login button</blockquote><blockquote><strong>Then</strong> he should login to both systems and be presented with the home page</blockquote><h3>How a UI test can meet the 3 conditions and act as a specification?</h3><p>The above specification can surely be re-written as a UI test in the following way.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rTgGKaQGr48gFJcJI0XK5A.png" /></figure><p>It is important to note that we should always choose to control the network using stubs (avoiding the flakiness of the real network is a must have for any robust UI test suite) and also any feature flag that might affect our scenarios.</p><p>Let’s see how each of the 3 conditions can actually be met:</p><h4>✅ 1. They should not change after a refactor</h4><p>It is quite obvious that a UI test changes if and only if requirements change. After all it is nothing more than a translation of the BDD scenario and thus does not depend on the underlying implementation nor does it change when refactoring it. So we can check condition #1 from our list.</p><h4>✅ 2. They must be written in a clear, easily understandable format</h4><p>Nevertheless, the problem with the way the above UI test is written compared with the BDD scenario, is that it is extremely more difficult for someone to understand and reason about it. A specification should be easily understood by everybody, non developer people as well.</p><p>Using the <a href="https://martinfowler.com/bliki/PageObject.html">Page Object pattern</a> (also known as the <a href="https://jakewharton.com/testing-robots/">Robot pattern</a>) we can refactor our UI test into a more declarative human readable format.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*llpZjeu6hqCmgfKm4O0g8A.png" /></figure><p>The UI test now achieves a level of clarity comparable to the BDD scenario, making it easily comprehensible. After all, as a specification it must be effectively communicated to others and be understandable when looking back at it sometime in the future. Thus we can check condition #2 as well.</p><h4>✅ 3. They should be expressive enough to uncover any hidden requirements</h4><p>It turns out that, when looked from a different perspective, <strong>UI tests really shine in expressing specifications that are missed or remain hidden in mobile apps</strong>.</p><p>Here are some examples of easy to miss requirements and how UI tests can help in revealing them:</p><p><strong><em>Missed loading states</em></strong></p><p>Well, one thing that is easily missed in the mobile world is defining exactly how the <strong>loading state</strong> looks like. No more guessing or asking around how loading should look like. We can explicitly define it when writing the spec inside the UI test. And also enforce it by the way when this is implemented!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3VpL2YM0MdZ4aeJrq_52Rg.png" /></figure><p><strong><em>Missed error states</em></strong></p><p>The same applies for <strong>error states</strong> or different flows that are triggered by specific API error codes. You can simply control the network response by using stubs and create additional UI tests that define those specs as well. Like in this non-happy path scenario where the login call returns the <strong><em>noLongerSupported</em></strong> API error and the user is asked to <strong>force update the app</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nAVebbqt5NuZGVAv_-13eg.png" /></figure><p>Non-happy scenarios are notoriously easy to miss during implementation and extremely time consuming to test. Having a UI test as a specification (along with using network stub responses) is the only way to ensure that this non-happy behaviour will be implemented and will not regress in the future. I call that piece of mind for the whole team 🧘</p><p><strong>It turns out that that there are specifications that will never show up in the UI itself. They will remain hidden in what happens in the background. </strong>Here are some examples.</p><p><strong><em>Hidden interaction with the API</em></strong></p><p>How our app interacts with the backend, which API calls are made and in what order is definitely a specification that needs to be agreed upon before implementation. And one that can never be exposed as part of a related BDD scenario.</p><p>Revealing this hidden spec is actually quite easy. We can record all the HTTP calls that are made during the test execution and use an inline snapshot that flushes and asserts all done up to that point in time.</p><p>In our backend migration example, the snapshot would need to assert that authentication is being made to both old and new backend.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GG4phlRRkw02-KRmv7C6JA.png" /></figure><p>Thus, when writing a UI test as a specification, one can also specify which specific endpoints are being called making it pretty clear to the developer what needs to be done in terms of API interaction to support this flow.</p><p>I think the above method is actually quite powerful for the following reasons:</p><ul><li>It <strong>enforces how the interaction with the backend is upon implementation</strong>, leaving no room for ambiguity or miscommunication (even for divergence between Android and iOS implementations)</li><li>It <strong>asserts that nothing changes in the future</strong>. It <strong>catches unintended deletion or addition of API calls</strong> and <strong>stops duplicate calls crawling in our flows</strong>, which is something that can remain hidden for a long time if something critical is not broken.</li><li>It serves as the <strong>perfect documentation of the interaction with the server</strong>. If at any point in time, somebody asks you what are the API calls involved in a specific flow, especially in complex flows like the login one in our app, you do not have to provide a guess by asking someone with context, or try to remember, or try to follow the code and find the answer, or even open a network proxy and see what is being recorded. And do it twice for Android and iOS… With this technique, you will quickly know the correct answer every time, with 100% certainty. And everybody in the team will know too 😎</li></ul><p><strong><em>Hidden analytics events / audit logs</em></strong></p><p>Using the same method, you could specify and reveal any other business critical operations that happen in the background, like analytics and audit logs. Providing regression detection for those at the same time! <em>P.S. This argument is so strong it never gets old 😈</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Ip5-LN2MqxaLLz2nxnM9ag.png" /></figure><p>Using the UI tests in the ways we presented above, it becomes obvious that the expressive power of the UI tests can go beyond the mere specification of user flows, revealing specifications that remain hidden and are difficult to be specified. We can finally check condition #3, the final condition from our list, establishing that UI tests can be used to write specifications for mobile apps.</p><p>There are other ways to expand the UI tests and reveal easy to miss or hidden specifications, but it should be clear by now that they can certainly add a lot of value to this dimension and thus become an efficient solution to the problem of <strong><em>missing specifications, </em></strong><a href="https://medium.com/@ge.sotiropoulos/shifting-ui-tests-to-the-far-left-6784f798acc2#cc90"><strong><em>the second most important problem when writing specifications</em></strong></a><strong><em>.</em></strong></p><p>In <a href="https://medium.com/@ge.sotiropoulos/shifting-ui-tests-to-the-far-left-part-2-a8a5c8b71df1"><strong>part 2 of the article</strong></a><strong> </strong>we will explore how one can quickly write UI tests before any coding starts and how this methodology addresses communication flaws, the other important problem when writing specifications.</p><p><strong>P.S. If you wish to dig more into this exciting topic, you could register for the amazing </strong><a href="https://swiftcraft.uk"><strong>Swift Craft conference</strong></a><strong> (in Southern England between 21–24 of May), where I will be holding a 3 hour workshop on this matter on the 22nd of May.</strong></p><h3>References — Further reading</h3><p>[1] The <a href="http://www.re-survey.org/#/explore">NaPiRE Project</a> (2016), <a href="https://elib.uni-stuttgart.de/bitstream/11682/8847/3/EMSE-D-15-00239_postprint.pdf"><strong><em>Na</em></strong><em>ming the </em><strong><em>P</em></strong><em>ain </em><strong><em>i</em></strong><em>n </em><strong><em>R</em></strong><em>equirements </em><strong><em>E</em></strong><em>ngineering: Contemporary Problems, Causes, and Effects in Practice</em></a></p><p>[2] This <a href="https://twitter.com/GergelyOrosz/status/1363058713347694592?lang=el">tweet</a> from <a href="https://twitter.com/GergelyOrosz">@GergelyOrosz</a> introduced me to PRDs and why they are needed.</p><p>[3] I have often found myself triaging such issues and thinking if I should just ignore the lack of consistency between Android and iOS and accept that this might be an insolvable problem.</p><p>[4] Various methods are available for writing specifications, including natural language, input-output examples, <a href="https://en.wikipedia.org/wiki/Behavior-driven_development">behavior-driven development (BDD) scenarios</a>, <a href="https://www.hillelwayne.com/post/decision-table-patterns/">decision tables</a>, <a href="https://en.wikipedia.org/wiki/State_diagram">state diagrams</a>, <a href="https://en.wikipedia.org/wiki/Flowchart">flow charts</a> and <a href="https://statecharts.dev/">Harel statecharts</a>. Each method is bounded by its expressive power with the more advanced ones allowing for more accurate modelling of the behaviour of the system, leaving no room for overlooked specifications. <strong>None of the above act as regression tests at the same time though</strong>. They remain disconnected from the actual implementation.</p><p>[5] I have to admit that I have come to these 3 conditions from hands-on experience. My impression is that treating tests as specifications is a subject that has remained under the radar of the tech community with lots of hidden potential. Maybe there is bibliography for this, maybe there isn’t but I would argue that at least these 3 conditions are a minimum subset of any condition set someone might come up with.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6784f798acc2" width="1" height="1" alt=""><hr><p><a href="https://medium.com/xmglobal/shifting-ui-tests-to-the-far-left-6784f798acc2">Shifting UI tests to the far left (part 1)</a> was originally published in <a href="https://medium.com/xmglobal">XM Global</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Snapshot Testing. Testing the UI and Beyond (Part 3)]]></title>
            <link>https://medium.com/xmglobal/snapshot-testing-testing-the-ui-and-beyond-part-3-860bd9e175b8?source=rss-f1e944862e90------2</link>
            <guid isPermaLink="false">https://medium.com/p/860bd9e175b8</guid>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[snapshot-testing]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[testing]]></category>
            <dc:creator><![CDATA[Sotiropoulos Georgios]]></dc:creator>
            <pubDate>Fri, 27 Nov 2020 08:48:22 GMT</pubDate>
            <atom:updated>2020-11-30T13:33:51.691Z</atom:updated>
            <content:encoded><![CDATA[<p><em>This is the final part of a posts series that aims to provide a complete overview of snapshot testing and its use cases, helping the developers understand what problems it can solve effectively and how to make it part of their software verification tools.</em></p><p><em>With </em><a href="https://medium.com/@ge.sotiropoulos/snapshot-testing-testing-the-ui-and-beyond-part-1-2369c9f84032"><em>part 1</em></a><em> focusing on describing how one should approach screenshot testing in mobile UI development, </em><strong><em>this final part illustrates how this can be done in practice</em></strong><em>. An </em><strong><em>iOS hands-on guide</em></strong><em> that I hope you will find useful.</em></p><p><em>Therefore, for a better understanding of the context, it is strongly recommended to read </em><a href="https://medium.com/@ge.sotiropoulos/snapshot-testing-testing-the-ui-and-beyond-part-1-2369c9f84032"><em>part 1</em></a><em> first before continuing.</em></p><p><em>P.S. </em><a href="https://medium.com/@ge.sotiropoulos/snapshot-testing-testing-the-ui-and-beyond-part-2-e56b0016d491"><em>Part 2</em></a><em> goes beyond UI testing and explores other interesting non-UI related applications. Backend people might find this interesting as well.</em></p><p>Before applying snapshot testing in our project, we need to define a <a href="https://medium.com/@ge.sotiropoulos/snapshot-testing-testing-the-ui-and-beyond-part-1-2369c9f84032#2f49">device configuration matrix</a> that lays out our strategy for testing against multiple device configurations (language, device size, theme, dynamic font size).</p><p>The device configuration matrix groups the configurations that one must test into two final configurations. A <strong>large</strong> one (common device size, light theme, and default font size) and a <strong>small</strong> one (small device size, dark theme, and XXXLarge font size). Let’s take a look at how this translates into code.</p><h3>Device configuration matrix in practice</h3><p>We will be using the <strong>core-testing¹ library</strong>, an iOS snapshot testing utility library that we created. It is built upon the excellent <a href="https://github.com/pointfreeco/swift-snapshot-testing">SnapshotTesting</a> library provided by the <a href="https://www.pointfree.co">PointFree</a> team and extends it by providing structured snapshot configuration generation.</p><h4>Testing screens</h4><p>For <strong>testing how a UIViewContoller looks like when it covers the full screen</strong>, the library defines the following three public <strong>snapshot configuration generator functions</strong>.</p><pre>SnapshotTestConfig.<strong>VC.large</strong> { config in ... }<br>SnapshotTestConfig.<strong>VC.small</strong> { config in ... }<br>SnapshotTestConfig.<strong>VC.all</strong> { config in ... }</pre><p>where “<strong><em>all”</em> generates both large and small configurations</strong> (the closure is going to be called twice). These functions are defined <a href="https://github.com/gsoti/core-testing/blob/master/CoreTesting/Classes/SnapshotTesting/SnapshotTestConfig%2BVC.swift">here</a>.</p><p>The assertion happens inside the closure using the configuration that it is passed, as can be seen in the example below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/866/1*1-d6AWEqlwhWQ4n94DjwOg.png" /><figcaption>Example usage of a configuration generator function</figcaption></figure><p>You can check the <em>DocumentHistoryViewController</em> snapshot tests example in core-testing found <a href="https://github.com/gsoti/core-testing/blob/master/Example/CoreTesting/DocumentHistory/DocumentHistoryViewControllerTests.swift">here</a>.</p><h4>Testing views</h4><p>Also for <strong>testing a UIView in isolation</strong>, the library defines the aforementioned three public snapshot configuration generator functions.</p><pre>SnapshotTestConfig.<strong>View.large</strong> { config in ... }<br>SnapshotTestConfig.<strong>View.small</strong> { config in ... }<br>SnapshotTestConfig.<strong>View.all</strong> { config in ... }</pre><p>These generators are used for testing (<strong>full width, dynamic height) </strong>views (i.e. views that span the full width of the screen and their height is dynamically defined by its content), like a <strong>UITableViewCell</strong>. You can check the <em>DocumentHistoryCell</em> snapshot tests example in core-testing found <a href="https://github.com/gsoti/core-testing/blob/master/Example/CoreTesting/DocumentHistory/DocumentHistoryCellTests.swift">here</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/828/1*YTqee-M6HPBv0ZxumJuqNQ.png" /><figcaption>full width, dynamic height view example</figcaption></figure><p>The library also provides the following two extra configuration generator functions for dealing with view specific scenarios that are not covered by the (full-width, dynamic height) configurations.</p><pre>SnapshotTestConfig.<strong>View.fixed(fixedSize)</strong> { config in ... }<br>SnapshotTestConfig.<strong>View.free</strong> { config in ... }</pre><p>The <strong>fixed</strong> configuration generator is used for testing <strong>(fixed width, dynamic height), (dynamic width, fixed height)</strong>,<strong> </strong>or<strong> (fixed width, fixed height) </strong>views. Similar to the <em>“all”</em> generator, two configurations as defined in the configuration matrix (the light theme — default font size, and the dark theme — XXXLarge font size) are generated. The only difference is that <strong>the size is fixed in one or both dimensions</strong>.</p><p>The six subviews of the following example should be tested using a (fixed width, dynamic height) configuration generator. We need to <strong>fix the width to a specific size</strong> (1/3 of the screen width and not the full width) and allow it to grow in height. The XXXLarge font size configuration will reveal if the content fits inside the view nicely.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/746/1*2xk17yPebaf6e4yPuSg5xg.png" /><figcaption>fixed width, dynamic height view example</figcaption></figure><p>The free configuration generator is used for <strong>(dynamic width, dynamic height)</strong> views, that take as much space as needed to accommodate for their content, like a custom UIButton. Similar to the <em>“all”</em> generator, two configurations as defined in the configuration matrix (the light theme — default font size, and the dark theme — XXXLarge font size) are generated. The only difference is that <strong>the size always adjusts to the growing content</strong>. You can check the <em>SupportButton</em> snapshot tests example in core-testing found <a href="https://github.com/gsoti/core-testing/blob/master/Example/CoreTesting/SupportButton/SupportButtonTests.swift">here</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/120/1*Vet1LiquuD2G1-4ioXdlRQ.png" /><figcaption>dynamic width, dynamic height view example</figcaption></figure><h4>Testing how the view reacts to changes in the environment</h4><p>While writing the snapshot test, if you instantiate the view outside of the configuration generator closure, the same instance of the view is tested in both configurations. Thus, as a nice side effect, when the configuration is changed, you also get to <strong>test how your view adapts to interface style (dark/light theme) and dynamic text size changes in the runtime</strong>.</p><h3>Applying screenshot testing in practice</h3><p>Let’s assume that we would like to use screenshot testing to develop and test the account info screen in our Forex trading app. The account info screen is the screen where the user can see his balance, profit and loss, and other account-related information.</p><p>This is how it should look like (for a demo account) according to the designs.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/1*cSjtnBAd8d_0RCwr7rm8zg.png" /><figcaption>Account info screen</figcaption></figure><p>Let’s see how we apply step by step everything we learned in <a href="https://medium.com/@ge.sotiropoulos/snapshot-testing-testing-the-ui-and-beyond-part-1-2369c9f84032">part 1</a> using the snapshot configurations generated by the core-testing library¹.</p><h3>Testing all device configurations</h3><p>We must <strong>always start by testing how the view looks like in all device configurations</strong>. We will be using the core-testing library to help us set up the screenshot tests. Here is how the test case looks like.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LqVDWSSqqeUQ2R5z620kUg.png" /><figcaption>Snapshot test for all device configurations</figcaption></figure><ol><li><strong>Create a view model object</strong> (which is the dependency of the view that we would like to test)</li><li><strong>Configure the view with the view model</strong> (in this case it is a view controller since we want to test the whole screen)</li><li><strong>Generate the snapshot configurations</strong> (in this case we want to generate all device configurations for a view controller as defined in our <a href="https://medium.com/@ge.sotiropoulos/snapshot-testing-testing-the-ui-and-beyond-part-1-2369c9f84032#2f49">configuration matrix</a>)</li><li><strong>Snapshot the view rendered with the provided configuration</strong></li></ol><p>If it is the first time the test is run (or the test is run explicitly in record mode), it will save the snapshot as a reference on the disk. Otherwise, the test will assert that the reference snapshot and the new one match.</p><p>The following two reference screenshots are generated.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/599/1*FTeH69eQyGfUb5ABpvBKGg.png" /><figcaption>Screenshot for the large configuration</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/516/1*a624_O2ZQkNAD8Dx_Ga5JQ.png" /><figcaption>Screenshot for the small configuration</figcaption></figure><p>In this way, we can check how <strong>the view looks like in both large and small configuration</strong> and as you can see, there is a problem with small width devices (like iPhone SE) when users have selected larger dynamic font size.</p><p><strong>Important:</strong> To avoid flakiness, please remember to always run all snapshot tests of your project against the same iPhone simulator (e.g. iPhone 11).</p><h3>Testing domain cases</h3><p>After fixing how the view looks like in the small configuration, we now should check <strong>how it looks like in all other domain cases</strong>. That means we should at least write tests for</p><ul><li>a <strong>demo</strong> user</li><li>a <strong>real</strong> user that has been <strong>validated</strong></li><li>a <strong>real</strong> user that has <strong>not</strong> been <strong>validated</strong></li></ul><p>And since device configurations have been already checked, we can perhaps now <strong>test the domain cases against only the large configuration</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5g4LW7Lz9YEB7pMJ6JZLiQ.png" /><figcaption>Snapshot test for the demo user case</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jfLFh6lKkeOW1XbYcu2HJg.png" /><figcaption>Snapshot test for the real user case (validated)</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VE-iKghUnu0GhhZf1QXUWA.png" /><figcaption>Snapshot test for the real user case (not validated)</figcaption></figure><p>And this is how the view looks like for a real user (validated or not).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/598/1*hJhd0LWh8M9QKgFXKB8zNQ.png" /><figcaption>Screenshot for a real user (validated)</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/598/1*g6R4i5w5UA22MOU2EjG0zA.png" /><figcaption>Screenshot for a real user (not validated)</figcaption></figure><h3>Discovering missing domain cases</h3><p>If you want to make sure that you have covered all possible domain cases, then you can <strong>check which parts of the view UI code are not covered by the code coverage</strong> 😀. Needless to say that having clean views that only deal with the UI and have no business logic really helps here.</p><p>Take a look at the example below. Using code coverage report integration with Xcode, we can quickly spot that we are probably missing a case where an extra label is presented as a warning if the margin drops below 50%.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AhuhHlwWY1ze9qv_nyZKOQ.png" /><figcaption>Code coverage reporting missing domain case</figcaption></figure><p>This seems quite important and as you can imagine it should be covered under a separate screenshot test.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/598/1*7yL_tuPXrG9YzfrM3l-8CQ.png" /><figcaption>Missing domain case</figcaption></figure><p>Having covered all device configurations and domain UI cases, the view has been fully tested and more importantly future-proofed against UI regression errors.</p><p>This hands-on guide concludes the 3 part posts series and everything you need to know about snapshot testing. You can follow me on <a href="https://twitter.com/qqefy">Twitter</a> and <a href="https://www.linkedin.com/in/gesotiropoulos/">LinkedIn</a> for more.</p><h3>References — Further reading</h3><p>[1] <a href="https://github.com/gsoti/core-testing">Core testing library</a>. This is a fork of the <a href="https://github.com/trading-point/core-testing">original</a> we use in XM, as I wanted to adjust it to the content of this posts series. Feel free to play with both and open a PR for feedback.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=860bd9e175b8" width="1" height="1" alt=""><hr><p><a href="https://medium.com/xmglobal/snapshot-testing-testing-the-ui-and-beyond-part-3-860bd9e175b8">Snapshot Testing. Testing the UI and Beyond (Part 3)</a> was originally published in <a href="https://medium.com/xmglobal">XM Global</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Snapshot Testing. Testing the UI and Beyond (Part 2)]]></title>
            <link>https://medium.com/xmglobal/snapshot-testing-testing-the-ui-and-beyond-part-2-e56b0016d491?source=rss-f1e944862e90------2</link>
            <guid isPermaLink="false">https://medium.com/p/e56b0016d491</guid>
            <category><![CDATA[snapshot-testing]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[mobile]]></category>
            <category><![CDATA[testing]]></category>
            <dc:creator><![CDATA[Sotiropoulos Georgios]]></dc:creator>
            <pubDate>Thu, 19 Nov 2020 00:48:01 GMT</pubDate>
            <atom:updated>2020-11-30T13:32:00.705Z</atom:updated>
            <content:encoded><![CDATA[<p><em>This is part 2 of a posts series that aims to provide a complete overview of snapshot testing and its use cases, helping the developers understand what problems it can solve effectively and how to make it part of their software verification tools.</em></p><p><em>While </em><a href="https://medium.com/@ge.sotiropoulos/snapshot-testing-testing-the-ui-and-beyond-part-1-2369c9f84032"><em>part 1</em></a><em> is focused on mobile UI development, this part goes beyond UI testing and explores other interesting non-UI related applications. For understanding what is snapshot testing and how it works, take a look at the intro of </em><a href="https://medium.com/@ge.sotiropoulos/snapshot-testing-testing-the-ui-and-beyond-part-1-2369c9f84032"><em>part 1</em></a><em>. </em><a href="https://medium.com/@ge.sotiropoulos/snapshot-testing-testing-the-ui-and-beyond-part-3-860bd9e175b8"><em>Part 3</em></a><em> is an iOS hands-on guide that illustrates how UI testing can be done in practice.</em></p><h3>Beyond Testing the UI</h3><p>Snapshot testing is by no means limited to testing the UI. As we will see, it has lots of other interesting use cases. By listing some examples in this part of the posts series, I will try to highlight the versatile nature of snapshot testing as a rather effortless testing tool that mainly fits well under the integration testing spectrum of the software verification methodologies. And hopefully, convince you that it can become a significant part of your testing tools.</p><h3>Testing complex data structures</h3><p>Testing complex data structures that have <strong>lots of properties</strong> usually requires writing lots of unit tests. This of course requires time and increases maintainability.</p><p>But if you can produce a textual representation of the complex data structure (like an HTTP request as the example shown below), you could use this as a snapshot and snapshot test it, and <strong>with a single assertion test all properties at once</strong> (the method, the URL, the headers, the body, etc).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/394/1*JhwqhTX6LmJXSEdjrSaOrA.png" /><figcaption>The diff of an HTTP request snapshot</figcaption></figure><p>Moreover, if the complex data structure can be easily converted to JSON (like an API response), then basically for free a <strong>JSON snapshot</strong> would also test all properties at once, avoiding even to come up with a textual representation for it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/662/1*4V_kaWSUD7s8nmdgAxsJPA.png" /><figcaption>A JSON snapshot</figcaption></figure><h3>Testing complex data formats</h3><p>In a similar fashion, if you write libraries or programs that produce an output with a complex data format, snapshot testing can be proven really helpful.</p><p>Imagine that your program generates <strong>PDF</strong> files and you would like to test that. In the unit test world, you would have to write multiple assertions as the PDF is a very complex data format. Instead, you could just produce an image of the generated PDF and use that as a snapshot applying again a single assertion, while also revealing how the PDF looks like.</p><p>You can check how <a href="https://github.com/WeirdMath/SwiftyHaru/tree/dev/Tests/SwiftyHaruTests">this Swift library</a> for generating PDF files is actually using snapshot tests for verifying its correctness, and how people even build <a href="https://spin.atomicobject.com/2018/02/07/pdf-snapshot-testing-node/">their own custom snapshot process</a> for testing that their generated PDFs do not change.</p><p>The same is true for programs that produce for example <strong>XML</strong>, <strong>HTML</strong>, or even <strong>code</strong>, where in the latter case you could easily reason about the generated code by just looking at the snapshots (see <a href="https://kentcdodds.com/blog/effective-snapshot-testing#babel-plugin-tester">here</a>) or even use the compiler to further validate its correctness (see <a href="https://www.pointfree.co/episodes/ep55-swift-syntax-command-line-tool">here</a>). Pretty amazing stuff to be honest!</p><h3>Testing log and analytics events</h3><p>If you need to make sure that <strong>critical paths of the code (e.g. the login flow) are always covered by logs</strong>, you would of course need to write tests for that.</p><p>Testing with unit tests would mean asserting every log event in the flow along with its properties (valuable debug information that needs to be logged). Instead, you could avoid the hassle and just write one single snapshot test that prints all log messages, in the order they should appear, along with their respective properties.</p><p>And you also get to expose them in a very <strong>human-readable way</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/598/1*fKFos6l18_gFWErxYqmxow.png" /><figcaption>A text snapshot of log events</figcaption></figure><p>Along the same lines, people are actually snapshot testing warnings and errors that their CLI tools produce (see <a href="https://kentcdodds.com/blog/effective-snapshot-testing#error-messages-and-logs">here</a>).</p><p>Likewise, you can snapshot test the sequence of the <strong>analytics events</strong> (along with their properties) in a business-sensitive funnel and <strong>make sure the funnel does not break⁷</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/558/1*EP8gfrpLWQUq4uHrVt2InA.png" /><figcaption>A text snapshot of analytic events</figcaption></figure><h3>A way to explore your domain</h3><p>It should be pretty evident by now that <strong>readability is an intrinsic characteristic of snapshot testing</strong>. It is also its greatest strength as <strong>its output is by far the easiest to reason abou</strong>t.</p><p>This is why snapshot testing is an ideal way to quickly <strong>expose and explore your domain</strong> that could otherwise remain hidden. Just take a look at how the output of a snapshot test could expose all <strong>API error logs</strong> related to a specific API endpoint in a very human-readable way.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/612/1*sihwgEQFFxVuDoEvUuPvxg.png" /><figcaption>All API error logs for POST /orders endpoint</figcaption></figure><p>And since it is quite often that you only discover that some extra debug information might be missing from the error logs only when already in production³, you also get to see how your logs look like before going to production and reason about them.</p><p>Also, take a look at how the <strong>output of your custom date formatter</strong> changes when the language changes. Snapshot test makes setting up something like that almost effortless.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/678/1*NyWDJ8E6vh-tvyB5if6oug.png" /><figcaption>Snapshot of different locale dates representation</figcaption></figure><p>Without the convenience of setting up a snapshot test for this, probably nobody would go the extra mile to check how dates are represented for different locales (something that users will see anyway). And that would remain hidden.</p><p>And as a nice side effect, snapshot tests’ output <strong>also acts as documentation</strong> for the developer and perhaps QA or business people.</p><h3>A change detector</h3><p>Snapshot tests are essentially a change detector. And as such, they are ideal for writing <strong>characterization tests⁴</strong> (also known as Golden Master Testing) when refactoring legacy code.</p><p>When refactoring the legacy code, you want to lock the behavior to a <strong>golden master version</strong> and you are <strong>only interested in whether the output has changed and not about whether it is correct</strong>.</p><p>Thus, snapshot tests, as a low effort method that tests multiple properties at once using a single assertion, are ideal in this case. You can check <a href="https://codeclimate.com/blog/gold-master-testing/">here</a> how Code Climate uses snapshot tests for writing Golden Master Testing.</p><p>They are also ideal when we want to <strong>track if something changed due to a change in an external dependency that we do not control</strong>, like an external system, or an <strong>external API</strong> or even <strong>external libraries</strong> that we would like to update from time to time.</p><p>Imagine that your program output depends on an external parser library that is currently at version 1. And we want to make sure the output remains unchanged when we update the parsing library to version 2. We can use snapshot testing to quickly capture the output when the library is at version 1, update the library and check if the output is the same and the test passes.</p><h3>Testing accessibility</h3><p>One of the most mind-blowing applications of snapshot testing is <strong>accessibility testing</strong>.</p><p>The <a href="https://github.com/cashapp/AccessibilitySnapshot">AccessibilitySnapshot</a> iOS library by CashApp produces an image snapshot of your view with <strong>all of the accessibility elements highlighted using different colors, along with an ordered list of the descriptions that VoiceOver will read</strong> for each of the elements⁶.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jCdjJK4z_7wbZJ5b3QOrqA.png" /><figcaption>An accessibility snapshot</figcaption></figure><p>And if the accessibility elements of this view ever change (for example the grouping of the payment-related middle row elements breaks — see next image), the test will fail.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*f2yHHWyPt2xuJfg87t2Ezw.png" /><figcaption>Regressed accessibility snapshot</figcaption></figure><p>It is pretty clear in this case as well that snapshot tests not only protect you against regression errors but also manage to expose the domain in a very <strong>human-readable way</strong>. I cannot think of a better and faster way to reason about which elements of the screen are accessible and in what order other than a simple image. Once again 🤯 Also check this <a href="https://github.com/playbook-ui/accessibility-snapshot-ios">one</a></p><h3>Potential pitfalls</h3><p>Of course, there also are some pitfalls about snapshot tests that we should all be aware of.</p><ol><li><strong>Effortless to update</strong> but <strong>easier to accept new snapshots with bugs</strong>. This is why snapshots need proper and thorough code review.</li><li>Since the expected output is missing (hidden inside the snapshot artifact), the <strong>context of what you test is lost</strong>. This is why we need to write really solid test descriptions.</li><li>They <strong>might lead to fragile tests</strong> as they test multiple properties at once and a minor change in any of them (even ones that might not be of interest) will break the test. This is why we need to keep them small.</li><li>They <strong>increase the git repository size</strong>, especially when doing screenshot testing. Maybe git LFS could be a solution?</li></ol><h3>Tools</h3><p>For <strong>iOS</strong> projects, one should check the excellent <a href="https://github.com/pointfreeco/swift-snapshot-testing">SnapshotTesting</a> library provided by the amazing <a href="https://www.pointfree.co">PointFree</a> team that handles both text and iOS image snapshots.</p><p>Every iOS developer should also check the variety of snapshot strategies that this library supports. You will find strategies for things like CGPath, UIBezierPath, WKWebView, URLRequest and so much more. Really inspiring work by the <a href="https://www.pointfree.co">PointFree</a> 🥇.</p><p>For <strong>Kotlin</strong> projects,<strong> </strong>the options are the <a href="https://github.com/Karumi/KotlinSnapshot">KotlinSnapshot</a> by Karumi when it comes to text snapshots and the <a href="https://github.com/Karumi/Shot">Shot</a> library by Karumi or the most recent <a href="https://github.com/cashapp/paparazzi">Paparazzi</a> by CashApp when it comes to Android image snapshots.</p><p>For the <strong>Web</strong>,<strong> </strong>the leader and pioneer in snapshot testing is the <a href="https://jestjs.io/docs/en/snapshot-testing">Jest</a> library.</p><p>You can follow me on <a href="https://twitter.com/qqefy">Twitter</a> and <a href="https://www.linkedin.com/in/gesotiropoulos/">LinkedIn</a>.</p><h3>References — Further reading</h3><p>[1] <a href="https://github.com/pointfreeco/swift-snapshot-testing">https://github.com/pointfreeco/swift-snapshot-testing</a></p><p>[2] <a href="https://kentcdodds.com/blog/effective-snapshot-testing#babel-plugin-tester">https://kentcdodds.com/blog/effective-snapshot-testing</a></p><p>[3] Has happened to me multiple times and had to release a new version just to add some extra debug info that was missing.</p><p>[4] <a href="https://michaelfeathers.silvrback.com/characterization-testing">https://michaelfeathers.silvrback.com/characterization-testing</a></p><p>[5] For the sake of completeness, it is worth mentioning that some libraries also support an inline assertion mode, which avoids saving the reference snapshot on the disk and directly places it inline inside the test when the test is run in record mode. See <a href="https://jestjs.io/docs/en/snapshot-testing">here</a></p><p>[6] <a href="https://cashapp.github.io/2020-05-20/making-ios-accessibility-testing-easy">https://cashapp.github.io/2020-05-20/making-ios-accessibility-testing-easy</a></p><p>[7] <a href="https://dropbox.tech/mobile/how-we-ensure-credible-analytics-on-dropbox-mobile-apps">https://dropbox.tech/mobile/how-we-ensure-credible-analytics-on-dropbox-mobile-apps</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e56b0016d491" width="1" height="1" alt=""><hr><p><a href="https://medium.com/xmglobal/snapshot-testing-testing-the-ui-and-beyond-part-2-e56b0016d491">Snapshot Testing. Testing the UI and Beyond (Part 2)</a> was originally published in <a href="https://medium.com/xmglobal">XM Global</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Snapshot Testing. Testing the UI and Beyond (Part 1)]]></title>
            <link>https://medium.com/xmglobal/snapshot-testing-testing-the-ui-and-beyond-part-1-2369c9f84032?source=rss-f1e944862e90------2</link>
            <guid isPermaLink="false">https://medium.com/p/2369c9f84032</guid>
            <category><![CDATA[android]]></category>
            <category><![CDATA[snapshot-testing]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[mobile]]></category>
            <category><![CDATA[testing]]></category>
            <dc:creator><![CDATA[Sotiropoulos Georgios]]></dc:creator>
            <pubDate>Thu, 19 Nov 2020 00:24:25 GMT</pubDate>
            <atom:updated>2020-12-24T20:48:33.046Z</atom:updated>
            <content:encoded><![CDATA[<p><em>This posts-series aims to provide a complete overview of snapshot testing and its use cases, helping the developers understand what problems it can solve effectively and how to make it part of their software verification tools.</em></p><p><em>Part 1 is focused on mobile UI development while </em><a href="https://medium.com/@ge.sotiropoulos/snapshot-testing-testing-the-ui-and-beyond-part-2-e56b0016d491"><em>part 2</em></a><em> goes beyond UI testing and explores other rather interesting non-UI related applications. </em><a href="https://medium.com/@ge.sotiropoulos/snapshot-testing-testing-the-ui-and-beyond-part-3-860bd9e175b8"><em>Part 3</em></a><em> is an iOS hands-on guide that illustrates how this can be done in practice.</em></p><h3>What is snapshot testing?</h3><p>Snapshot testing is just a form of unit testing. In unit tests, you have a function, and given some input, you explicitly assert against the expected output.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/304/1*AtWLIPwLOXlzlphvozdHAQ.png" /></figure><p>The equivalent snapshot test would look like the following and as you can see the main difference is that there is no explicit expected output.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/271/1*U52bQjk-vF2_dBzgcexJsw.png" /></figure><p>But then, how does this work? Well, you can run a snapshot test in two modes.</p><ul><li>When running the test in <strong>record mode</strong>, a snapshot of the output is produced and saved as an artifact on the disk (just a simple text file).</li><li>When running the test in <strong>verify mode</strong> a snapshot of the output is produced, it then looks on the disk for a file of the previously saved reference snapshot, it compares the two and if they differ it fails with a nice error message.</li></ul><p>When the test fails, either the change is unexpected, or the reference snapshot needs to be updated to the new version. Finally, the snapshot artifact should be committed alongside code changes and reviewed as part of your code review process¹.</p><p>Classic assertion-based tests are perfect for testing clearly defined behavior that is expected to remain relatively stable. Snapshot tests are great for testing less clearly defined behavior that may change often. UI components often change in small and trivial ways. The copy is changed, whitespace is added, a border color is modified².</p><p>Snapshot testing is by no means a replacement of unit testing, but rather an additional test mechanism³.</p><h3>Testing the UI</h3><p>Ιn the mobile community the most popular form of snapshot testing is <strong>screenshot testing</strong>.</p><h3>Screenshot testing</h3><p>Screenshot testing is a visual regression testing method where the snapshot that you produce is an image of a part of the UI (could be a whole screen or just a single view).</p><h4>Comparing screenshots</h4><p>When you run the test in record mode, a reference image is saved on the disk.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rlGY41S9R26Vb6qmexpS-Q.png" /><figcaption>Record mode</figcaption></figure><p>Then every time you run it in verify mode, a newly generated image is produced and compared to the previously saved reference image.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cWe8O2jKwyt3KpBLA5t5uw.png" /><figcaption>Verify mode</figcaption></figure><p>If they differ, then the test fails and the failure diff would look like something like that.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8Ziw9sCr_0wqqr-Se-kDIw.png" /><figcaption>Failure diff</figcaption></figure><p>It is the same concept as before when snapshotting the output of a function, but instead of text as the produced artifact you now have an image, and instead of applying text comparison you now apply pixel by pixel comparison. If you can serialize your output into a format, like text or image, that can be saved to disk and you have a way to compare and produce a diff, then you can also apply snapshot testing.</p><h4>Benefits</h4><p>By adding screenshot testing into our mobile project, you have already gained quite a lot.</p><ul><li><strong>Trivial to write, </strong>almost<strong> effortless to update</strong></li><li>A fast way to <strong>verify what users see</strong> and also <strong>check how your view looks while developing</strong> (No need to fire up the simulator and navigate to a specific screen just to see how the view you are developing looks like. You just take a look at the produced image snapshot)</li><li>They provide <strong>far more coverage than a unit test normally allows</strong> (test multiple properties at once)</li><li>Plug them in the CI and detect UI regression errors</li></ul><h3>Device configurations</h3><p>These are all nice benefits but you should not stop here. To maximize what screenshot testing has to offer, you have to make sure that you test against all possible device configurations.</p><h4>Language</h4><p>You can quickly test how your view looks like in other languages and produce a screenshot for each language.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Zh5R960Z4kbcF_mj4SR7Zg.png" /><figcaption>Screenshot for the Greek language</figcaption></figure><p>Or instead of supporting multiple locales and multiple screenshots for them, you could just use one single <strong>pseudo-locale⁴</strong> to simulate strings with increased length and see how larger texts stress your UI.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ruhD63Ty9maoj-kz8XsJbA.png" /><figcaption>Screenshot for pseudo-locale</figcaption></figure><h4>Device size</h4><p>You can just as easily test how your view looks like on other devices and check, for example, if something does not fit in smaller devices.</p><h4>Theme</h4><p>If your app supports a dark theme, no problem... This can be tested as well.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1Jku_rRNQADEWmKeCrsxTg.png" /><figcaption>Screenshot for dark theme</figcaption></figure><h4>Dynamic font size</h4><p>Finally, you can also see how your view supports dynamic font size.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*S1beDL2CMBljyXf8ExIWbQ.png" /><figcaption>Screenshot for larger dynamic font size</figcaption></figure><h4>Device configuration matrix</h4><p>If you were to test each of the above configurations in a different snapshot test, you would inevitably end up with lots of generated reference screenshots. Instead, you can group different configurations and reduce the number of configurations that need to be tested. A <strong>configuration matrix</strong> helps you define your grouping strategy.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MTRShHobzHxTlinQDHUdtg.png" /><figcaption>Configuration matrix</figcaption></figure><p>In this example, we grouped everything in two configurations.</p><ul><li>The <strong>large</strong> configuration tries to be as close as possible to what the majority of the users will see (using the most common device size, theme, and font size) and possibly also matches the designs⁵.</li><li>The <strong>small</strong> configuration tries to check if everything still looks ok in small devices, using a dark theme and an XXXLarge font size.</li></ul><h3>Exploring the domain</h3><p>More importantly, screenshot testing also allows you to quickly see how the same view looks like in all different cases of your domain.</p><p>Let’s take a look at the view we have been using as an example so far. Its business purpose is to inform the user about when <em>the market is</em> <em>open</em> during the day.</p><p>Just by mocking your data, you can quickly have a look at what the view looks like when <em>the market is</em> <em>closed</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*C3GjNEoSNqgrsNESAiMTmA.png" /><figcaption>Different domain case (the market is closed)</figcaption></figure><p>or when <em>there are more than one open intervals</em>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VEHxYbxsXsM4XlEYeknpbg.png" /><figcaption>Different domain case (more than one open interval)</figcaption></figure><p>With screenshot tests requiring almost no effort to set up, exploring all the different UI domain cases has never been quicker and easier.</p><h3>The biggest benefits</h3><h4>Testing all device and domain configurations</h4><p>When you combine all the above, you will end up testing multiple configurations (localisations — theme — size — dynamic font size) all at once and be done with them early in the development phase.</p><p>In that way, you would have quickly tested cases that otherwise you would have never bothered to manually recreate and test. And most importantly if the CI has your back, you also avoid UI regression errors for all cases.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Is0uSALoD94SR5aovi6P8g.png" /><figcaption>All device and domain configurations</figcaption></figure><h4>The perfect pull request</h4><p>As a very nice side-effect, screenshot testing will change your workflow when developing the UI and how the PR would look like in that case.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1020/1*RDzMOwiceoM6F-pG8aOlKQ.gif" /><figcaption>The perfect pull request</figcaption></figure><ul><li>The <strong>view can and should be developed independently</strong>. You do not need to wait for the container of the view to be implemented first.</li><li>Thus the <strong>PR becomes quite concise</strong>, as it only contains the code for the view along with screenshots of how it will like in all possible UI cases.</li><li>More importantly, screenshots add a <strong>missing visual dimension to the code review</strong>, thus reducing cognitive effort for the reviewer. The code reviewer no longer has to try to imagine how the UI will look like, he can actually see it.</li></ul><h3>Other interesting use cases</h3><p>In the scope of the Composable Architecture, the PointFree team presented in <a href="https://www.pointfree.co/episodes/ep86-swiftui-snapshot-testing">episode 86</a> their solution on <strong>e2e functional tests</strong> using SwiftUI and snapshot testing. It is absolutely mind-blowing 🤯 and a must-watch.</p><p>This <a href="https://www.youtube.com/watch?v=tk0HzScvW2M&amp;feature=emb_logo">talk</a> (Testing and Declarative UI’s) by Nataliya Patsovska is about <strong>combining Xcode Previews and snapshot tests</strong>. Pretty interesting as well.</p><p>People have been using screenshot testing to build and test their app’s <strong>UI design system</strong> (see <a href="https://github.com/playbook-ui/playbook-ios">Playbook</a> for iOS and <a href="https://storybook.js.org/docs/react/workflows/snapshot-testing">Storybook</a> for Web)</p><p>Testing <strong>animations</strong> is also possible. We have been using it to test Lottie animations by taking snapshots of the animated view. Moreover, <a href="https://github.com/cashapp/stagehand">Stagehand</a>, a composable type-safe animation library from Cashapp, uses snapshot testing that can also generate animated PNG files to test its functionality. Similar concepts are described in this <a href="https://youtu.be/3BVkbWXcFS4?t=2060">talk</a>.</p><p>Finally, some people use as a snapshot the difference produced between two snapshots. In this way they can isolate what changed before and after you interacted with it and test just that. Check it out <a href="https://kentcdodds.com/blog/effective-snapshot-testing#snapshot-diff">here</a>.</p><h3>Tools</h3><p>For <strong>iOS</strong> projects, one should check the excellent <a href="https://github.com/pointfreeco/swift-snapshot-testing">SnapshotTesting</a> library provided by the amazing <a href="https://www.pointfree.co">PointFree</a> team.</p><p>Every iOS developer should also check the variety of snapshot <a href="https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Documentation/Available-Snapshot-Strategies.md">strategies</a> that this library supports. You will find strategies for things like CGPath, UIBezierPath, WKWebView, URLRequest and so much more. Really inspiring work by the <a href="https://www.pointfree.co">PointFree</a> 🥇.</p><p>For the sake of completeness, I would also like to mention the <a href="https://github.com/uber/ios-snapshot-test-case">iOSSnapshotTestCase</a> library, which is the very first library available for iOS.</p><p>For <strong>Android</strong> projects,<strong> </strong>the options are the <a href="https://github.com/Karumi/Shot">Shot</a> library by Karumi or the most recent <a href="https://github.com/cashapp/paparazzi">Paparazzi</a> by CashApp.</p><p><em>You can also check out </em><a href="https://medium.com/@ge.sotiropoulos/snapshot-testing-testing-the-ui-and-beyond-part-3-860bd9e175b8"><em>part 3</em></a><em> which is an iOS hands-on guide that illustrates how all the above are translated into code.</em></p><p><em>To go beyond UI testing and find out lots of examples of how snapshot testing could be used in a non-UI context, you can continue reading </em><a href="https://medium.com/@ge.sotiropoulos/snapshot-testing-testing-the-ui-and-beyond-part-2-e56b0016d491"><em>part 2</em></a><em>.</em></p><p>You can follow me on <a href="https://twitter.com/qqefy">Twitter</a> and <a href="https://www.linkedin.com/in/gesotiropoulos/">LinkedIn</a>.</p><h3>References — Further reading</h3><p>[1] <a href="https://jestjs.io/docs/en/snapshot-testing">Jest Snapshot Testing</a></p><p>[2] <a href="https://benmccormick.org/2016/09/19/testing-with-jest-snapshots-first-impressions/">https://benmccormick.org/2016/09/19/testing-with-jest-snapshots-first-impressions/</a></p><p>[3] <a href="https://www.thoughtworks.com/radar/techniques/snapshot-testing-only">https://www.thoughtworks.com/radar/techniques/snapshot-testing-only</a></p><p>[4] <a href="https://netflixtechblog.com/pseudo-localization-netflix-12fff76fbcbe">https://netflixtechblog.com/pseudo-localization-netflix-12fff76fbcbe</a></p><p>[5] As a next step, you could even produce a side-by-side comparison of the generated screenshots against the designs (exported directly from e.g. Figma). And using this to automatically augment the context of a pull requests for the code reviewer would be very nice indeed.</p><p>[6] <a href="https://www.stephencelis.com/2017/09/snapshot-testing-in-swift">https://www.stephencelis.com/2017/09/snapshot-testing-in-swift</a></p><p>[7] <a href="https://www.vadimbulavin.com/snapshot-testing-swiftui-views/">https://www.vadimbulavin.com/snapshot-testing-swiftui-views/</a></p><p>[8] <a href="https://osinski.dev/posts/snapshot-testing-self-sizing-table-view-cells/">https://osinski.dev/posts/snapshot-testing-self-sizing-table-view-cells/</a></p><p>[9] <a href="https://troz.net/post/2020/swiftui_snapshots/">https://troz.net/post/2020/swiftui_snapshots/</a></p><p><em>Special thanks to </em><a href="https://medium.com/u/2a1edb7d75ca"><em>Vagelis Koutkias</em></a><em> for introducing screenshot testing to the team a while ago (lots of the screenshots are actually part of that very first PR), and mentioning [5] while reviewing.</em></p><p><em>Special thanks to </em><a href="https://medium.com/u/ff76cd952853"><em>Nikos Linakis</em></a><em> for letting me use screenshots and terms from his initial article on </em><a href="https://medium.com/xmglobal/screenshot-testing-101-7dd24ca6b8ce"><em>Screenshot testing</em></a><em> and always coming up with the best terminology (“the perfect pull request” is all his).</em></p><p><em>Special thanks to </em><a href="https://medium.com/u/75a9412648f5"><em>Natalia Chalkidou</em></a><em> and </em><a href="https://medium.com/u/d3a9e3ccd21d"><em>Stelios Poulakakis</em></a><em> for their ideas about how one device configuration should match the designs.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2369c9f84032" width="1" height="1" alt=""><hr><p><a href="https://medium.com/xmglobal/snapshot-testing-testing-the-ui-and-beyond-part-1-2369c9f84032">Snapshot Testing. Testing the UI and Beyond (Part 1)</a> was originally published in <a href="https://medium.com/xmglobal">XM Global</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Priority first]]></title>
            <link>https://medium.com/xmglobal/priority-first-d98de4892f68?source=rss-f1e944862e90------2</link>
            <guid isPermaLink="false">https://medium.com/p/d98de4892f68</guid>
            <category><![CDATA[team-management]]></category>
            <category><![CDATA[product-management]]></category>
            <category><![CDATA[product-owner]]></category>
            <category><![CDATA[prioritization]]></category>
            <category><![CDATA[competitor-analysis]]></category>
            <dc:creator><![CDATA[Sotiropoulos Georgios]]></dc:creator>
            <pubDate>Fri, 22 Nov 2019 20:38:24 GMT</pubDate>
            <atom:updated>2019-11-26T05:42:55.459Z</atom:updated>
            <content:encoded><![CDATA[<h4>A modular feature prioritization framework</h4><p>Delivery on time, requirement analysis, roadmap planning, and people management are some of the things that a product owner or a manager has on his mind. However, the key to success for all the above is, without any doubt, being able to prioritize. This article presents a modular feature prioritization framework and acts as a self-fulfilling prophecy on my claim to treat priority as a priority.</p><p>Thinking strategically and roadmap planning for a product owner/manager will inevitably, at some point, require prioritizing features. Prioritizing tasks also appears as a necessity in technical teams whenever, for example, they need to plan technical debt tasks for the next sprints. This work is an endeavor of formalizing a process for doing so, and I hope it provides a consistent, standardized, and straightforward approach in the form of a framework. Hence the term <strong>Feature Prioritisation Framework</strong>.</p><p>As an engineer, and since I could not waste too much time on it, modularity and composability came as an essential requirement for it to be simple and extensible for future enhancements.</p><h3>Value vs. Effort</h3><p>We are going to apply the <strong>Value vs. Effort model¹</strong>, one of the most popular prioritization frameworks. It is essentially a cost-value analysis model that allows you to evaluate each feature based on how much business value it will bring and how difficult or complex it will be to implement it.</p><p>We assign initial (Value, Effort) value pairs for each of the features, and then we plot them on a scatterplot, as seen in the image below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/938/1*Ykzh6PWfbeF1KadLikB9cA.png" /></figure><p>The scatterplot allows for a quick comparative overview of all the features’ priorities. We even divide the chart area into four regions, each one forming a bucket of features that further help with the prioritization.</p><p>High Effort, High Value: <strong>long-term strategy</strong></p><p>Low Effort, High Value: <strong>quick wins</strong></p><p>Low Effort, Low Value: <strong>pet projects</strong></p><p>High Effort, Low Value: <strong>time sinks</strong></p><h3>Assigning initial weights</h3><p>To start putting features to the scatterplot, we need a way to calculate the initial values for Effort and Business Value².</p><h4>Choosing a scale</h4><p>The absolute values we assign to a feature do not really matter. For example, it makes no difference if we use values from the scale of <em>[0–100]</em> or <em>[0–200]</em> or any other<em>. </em>We choose a range and stick to it since the only thing that matters is the relative difference between the values. For that purpose, it is more suitable to think of these values as <strong>weights</strong>.</p><p>For example, if feature #1 (𝔽1) has double the Effort compared to feature #2 (𝔽2), we could assign weights to them like the following: <em>𝔽1=100 and 𝔽2=50</em>, or <em>𝔽1=200 and 𝔽2=100</em>, etc.</p><h4>Deciding on a methodology</h4><p>The methodology we follow to derive those initial weights is <strong>arbitrary</strong> but must be consistent. Every team can come up with a process that suits its needs and follow it. There is plenty of room here for devising smart and consensus-aware methodologies.</p><p>Here is an <strong>example</strong> of a consensus-aware decision strategy about Business Value weights³. Let’s say that a team of product stakeholders has to prioritize six features. Each stakeholder is given a bag of 6 weight units, where each weight is a number of the Fibonacci sequence. In our example, each stakeholder’s bag will have the following weights {1, 2, 3, 5, 8, 13}. In secret, he assigns a weight to each feature, and when everyone is done, the total weight for each feature is calculated. Finally, we normalize these weights to our scale of choice (e.g., <em>[0–100]</em>)⁴, making sure we preserve the relative differences between them.</p><p>The engineering team can, for example, follow a similar strategy when choosing initial Effort weights. Τhe weights themselves could be an estimation of the person-hours needed for task completion.</p><p>Once we decide on the methodology for calculating initial values for both Effort and Business Value, we can start adding features on the scatterplot.</p><h3>Considering multiple factors</h3><p>When calculating the Effort or the Business Value of a feature, it is often the case that the initial estimation of weights is not enough. A product owner or a team might also, and probably should, want to consider <strong>multiple factors</strong>.</p><p>For example, competition analysis (what features does the competition have or is missing), feedback analysis (e.g., comments on the App Store, feedback emails, questionnaires), user testing analysis (e.g., through interactive prototypes), etc. should affect the Business Value and should be taken into account.</p><h4>Every factor is a module that transforms the weights</h4><p>The proposed framework tries to do that in a simple, modular, and composable way. Every factor that we think should affect the weight of a feature is a <strong>stand-alone module</strong> that increases or decreases the existing weight. How the weight is changed, it depends on the module itself and the data we have in our possession.</p><p>For example, if we keep track of the user comments on the App Store asking for missing features, we could come up with a <em>“user feedback module”</em> that would increase the Business Value weight of all the features users are requesting.</p><p>It is entirely up to us to identify modules like the <em>“user feedback module”</em> that affect either the Business Value or the Effort, define how they change them in the form of a <strong>transformation function</strong>, and apply them. And since the transformation functions are of the form <strong><em>f: Value → Value</em></strong><em> </em>(endomorphism⁵), they <strong>compose</strong> infinitely. That means we can use any number of modules we want and <strong>chain them one after another in a plug-n-play fashion</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/591/1*CjDmBKnG7K2omuiyQNNUKg.png" /><figcaption>Module composition example</figcaption></figure><p>The power of compositionality is that it allows us to modify at any time the chain of modules by adding any other module we would like to affect e.g the Business Value or by removing an existing one. We could even apply normalization² after each module application to keep the weights within the selected scale.</p><p>Let’s have a look at two examples of how modules could look like, one for Business Value and one for Effort.</p><h3>An example module for Business Value</h3><h4>Competition analysis module</h4><p>Let’s assume that we want to factor in the competition status when calculating the Business Value weights. We start by identifying the competitors and writing down all the features that our application is missing, but the competitors might have in a <strong>competition analysis matrix</strong> like below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*e-yZ34Gz02fomZROHSv2Xw.png" /><figcaption>Competition analysis matrix</figcaption></figure><p>We note the presence of the feature in a competitor with an <strong>(X)</strong> and the absence with an <strong>(-)</strong>.<strong> </strong>Features like 𝔽3 that do not exist in our competitors but are something that we might be interested in implementing ourselves, we call them <strong>competitive advantages</strong>. Features like 𝔽2 that appear in all competitors except our application, we call them <strong>competitive disadvantages</strong>.</p><p>For example, we could choose to promote competitive advantages by 20% and competitive disadvantages by 10% (based on some reasoning that we should catch up with the competition), while applying no change to all other features.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/792/1*VFoPwbGi3_FCsbU_wmbSvw.png" /><figcaption>Competition analysis module transformation function</figcaption></figure><p>Applying the <em>“competition analysis module”</em> to our initial values will shift the Business Value weights in the scatterplot along the y-axis.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/938/1*5FZUVX3oR-uAM67bei-QLg.gif" /><figcaption>Competition analysis module affecting Business Value weights (y-axis)</figcaption></figure><h3>An example module for Effort</h3><h4>Implementation complexity module</h4><p>For this example, we will assume that we would like to factor in the implementation complexity of a feature when calculating the Effort. First, we would have to agree on how to model complexity. We could divide the tasks into <strong>high, medium, low, and none complexity</strong> and increase the weights accordingly.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/748/1*En9q7nMI1I8wtktax9dqdw.png" /><figcaption>Implementation complexity module transformation function</figcaption></figure><p>Again, it is essential to state that how we model complexity and how it transforms the Effort weights is entirely up to us. There is no magic number here; we only have to agree on something that suits our data and use that consistently. It is the same process as when defining a module for Business Value, but now the features on the scatterplot are shifted along the x-axis.</p><p>Below you can see an examples on how the features would be further affected when applying the <em>“implementation complexity module”</em> (we assume none complexity for 𝔽1 and 𝔽3).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/938/1*vUw_paszYkUhON_p_9XSqg.gif" /><figcaption>Implementation complexity module affecting Effort (x-axis)</figcaption></figure><h3>Conclusion</h3><p>The Effort-Value model makes prioritization of new features very clear and understandable by visualizing them on a scatterplot. The values that we feed the model, though, could be more than just once-off initial weights that we have chosen. What if there are multiple factors to consider when estimating the Business Value or the Effor? The current proposal extends the basic model to account for any other factor in a simple and plug-n-play fashion.</p><p>In this proposed framework, every factor is an independent module that can be plugged in and out whenever we want and can compose well with the other modules. The composable module is the core of this framework as it gives flexibility and increases our modelling capabilities.</p><p>This proposal is not about providing a concrete prioritization framework. It proposes something more powerful, <strong>a way to build a prioritization framework</strong> that can be extended and formed to meet the specific needs of each team. Thus, although I tried to present some module examples, every team should try to come up with their own based on intelligence and data they have in their possession. I cannot wait to see what you can come up with.</p><p>[1] <a href="https://www.mindtheproduct.com/enter-matrix-lean-prioritisation/">https://www.mindtheproduct.com/enter-matrix-lean-prioritisation/</a> <a href="https://www.productplan.com/glossary/value-vs-complexity/">https://www.productplan.com/glossary/value-vs-complexity/</a></p><p>[2] Usually, choosing values for the Business Value is done by the product team, and selecting values for the Effort is done by the project manager and the engineering team.</p><p>[3] <a href="https://en.wikipedia.org/wiki/Planning_poker">https://en.wikipedia.org/wiki/Planning_poker</a></p><p>[4] Every time we want to transform our values and keep them within an initially selected scale (e.g. [0–100]), we should normalize. We take the maximum weight, divide it with the maximum scale value, and compute a normalization factor. We then need to multiply all weights with this factor.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/810/1*IssHjULPdY53eGN_ka4RwQ.png" /><figcaption>Normalization function</figcaption></figure><p>[5] In mathematics, an <strong>endomorphism</strong> is a morphism from a mathematical object to itself. <a href="https://en.wikipedia.org/wiki/Endomorphism">https://en.wikipedia.org/wiki/Endomorphism</a>. The input and output are of the same type, and in our case, it is a function that takes as input a <em>value</em> and produces a value again. That enables us to compose them easily by chaining one after another.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d98de4892f68" width="1" height="1" alt=""><hr><p><a href="https://medium.com/xmglobal/priority-first-d98de4892f68">Priority first</a> was originally published in <a href="https://medium.com/xmglobal">XM Global</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>