<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Oleksandr Romanov</title>
    <description>The latest articles on DEV Community by Oleksandr Romanov (@al8xr).</description>
    <link>https://dev.to/al8xr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F361588%2F3dd40867-652c-472a-a2e8-b881f4b0a655.jpg</url>
      <title>DEV Community: Oleksandr Romanov</title>
      <link>https://dev.to/al8xr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/al8xr"/>
    <language>en</language>
    <item>
      <title>Books and courses about blockchain for (not so absolute) beginners</title>
      <dc:creator>Oleksandr Romanov</dc:creator>
      <pubDate>Tue, 18 Jan 2022 10:46:21 +0000</pubDate>
      <link>https://dev.to/al8xr/books-and-courses-about-blockchain-for-not-so-absolute-beginners-1h85</link>
      <guid>https://dev.to/al8xr/books-and-courses-about-blockchain-for-not-so-absolute-beginners-1h85</guid>
      <description>&lt;p&gt;Recently, several people reached me and ask - what resources I can recommend in order to build foundational knowledge about blockchain. &lt;/p&gt;

&lt;p&gt;Here is the list of books and courses that I finished during 2021-2022 by myself. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Books:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mastering Blockchain &lt;a href="https://lnkd.in/ekpsMwKR"&gt;https://lnkd.in/ekpsMwKR&lt;/a&gt; Recommended. &lt;/li&gt;
&lt;li&gt;Blockchain and decentralized systems &lt;a href="https://lnkd.in/eMqHtzWk"&gt;https://lnkd.in/eMqHtzWk&lt;/a&gt; Highly recommended.&lt;/li&gt;
&lt;li&gt;Grokking Bitcoin &lt;a href="https://lnkd.in/eSNDneH7"&gt;https://lnkd.in/eSNDneH7&lt;/a&gt; Maybe, if you want to deep dive into Bitcoin.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Courses on Coursera:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blockchain Specialization &lt;a href="https://lnkd.in/eRFgwFsK"&gt;https://lnkd.in/eRFgwFsK&lt;/a&gt; Recommended for full beginners.&lt;/li&gt;
&lt;li&gt;Blockchain Scalability and its Foundations in Distributed Systems &lt;a href="https://lnkd.in/ejUSRs8Z"&gt;https://lnkd.in/ejUSRs8Z&lt;/a&gt; Recommended for people with some background.&lt;/li&gt;
&lt;li&gt;Decentralized Finance (DeFi): The Future of Finance Specialization &lt;a href="https://lnkd.in/eEkRF8qU"&gt;https://lnkd.in/eEkRF8qU&lt;/a&gt; Recommended for those who interested in DeFi.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Courses on Udemy:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blockchain and Bitcoin Fundamentals &lt;a href="https://lnkd.in/e2k4Q_KD"&gt;https://lnkd.in/e2k4Q_KD&lt;/a&gt; Nice and gently intro to the blockchain.&lt;/li&gt;
&lt;li&gt;Blockchain Advanced Level: Uses Beyond Bitcoin &lt;a href="https://lnkd.in/esDEQg2M"&gt;https://lnkd.in/esDEQg2M&lt;/a&gt; More in-depth view to the blockchain world.&lt;/li&gt;
&lt;li&gt;Blockchain A-Z™: Learn How To Build Your First Blockchain &lt;a href="https://lnkd.in/eTcR6Ad2"&gt;https://lnkd.in/eTcR6Ad2&lt;/a&gt; Recommended. &lt;/li&gt;
&lt;li&gt;Ethereum Blockchain Developer Bootcamp With Solidity (2022) &lt;a href="https://lnkd.in/e-TEnNMh"&gt;https://lnkd.in/e-TEnNMh&lt;/a&gt; Recommended. Good way of teaching the code.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>blockchain</category>
      <category>course</category>
      <category>books</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Blockchain testing - a mindmap</title>
      <dc:creator>Oleksandr Romanov</dc:creator>
      <pubDate>Fri, 14 Jan 2022 07:45:03 +0000</pubDate>
      <link>https://dev.to/al8xr/blockchain-testing-a-mindmap-4ag3</link>
      <guid>https://dev.to/al8xr/blockchain-testing-a-mindmap-4ag3</guid>
      <description>&lt;p&gt;In my previous blog post, I shared a useful information on &lt;a href="https://dev.to/al8xr/what-does-it-mean-to-test-a-blockchain-and-which-knowledge-do-you-need-for-it-2gla"&gt;what does it mean to "test a blockchain"&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Today, I want to present a mind map of knowledge you need to learn in order to test blockchain and blockchain-based applications effectively. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Fxj_oyhf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z2ll1nwp6fsb2ctd8rf9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Fxj_oyhf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z2ll1nwp6fsb2ctd8rf9.png" alt="Image description" width="880" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feel free to suggest things that I may miss in this map. &lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>testing</category>
    </item>
    <item>
      <title>What does it mean 'to test a blockchain' and which knowledge do you need for it</title>
      <dc:creator>Oleksandr Romanov</dc:creator>
      <pubDate>Mon, 06 Dec 2021 08:32:53 +0000</pubDate>
      <link>https://dev.to/al8xr/what-does-it-mean-to-test-a-blockchain-and-which-knowledge-do-you-need-for-it-2gla</link>
      <guid>https://dev.to/al8xr/what-does-it-mean-to-test-a-blockchain-and-which-knowledge-do-you-need-for-it-2gla</guid>
      <description>&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@a_uem?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Akinori UEMURA&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/chain?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Blockchain is a hype topic nowadays. It seems that every other person is making their own cryptocurrency or opening a cryptocurrency exchange at the corner of the street :).&lt;/p&gt;

&lt;p&gt;To better understand what blockchain is and how does it work, I highly recommend these introductory videos: &lt;a href="https://youtu.be/SSo_EIwHSd4"&gt;1&lt;/a&gt; and &lt;a href="https://youtu.be/bBC-nXj3Ng4"&gt;2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But what blockchain brings to the testing world? How deeply do you need to know about blockchain to test with such systems?&lt;/p&gt;

&lt;p&gt;In this blog post, I will describe a few different cases of testing blockchains. Also, I will share my list of things you need to know to bring quality to such systems successfully.&lt;/p&gt;

&lt;h2&gt;
  
  
  Blockchain networks
&lt;/h2&gt;

&lt;p&gt;It is the most "hardcore" option. In this case, the entire blockchain network is tested - as a holistic solution. For example - verification of Bitcoin, Ethereum networks.&lt;/p&gt;

&lt;p&gt;What we test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;storing transactions in blocks and communication between them&lt;/li&gt;
&lt;li&gt;cryptographic encryption and key management protocols&lt;/li&gt;
&lt;li&gt;data replication between nodes in the network&lt;/li&gt;
&lt;li&gt;consensus algorithms&lt;/li&gt;
&lt;li&gt;system performance&lt;/li&gt;
&lt;li&gt;system security&lt;/li&gt;
&lt;li&gt;fault tolerance of the system&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Blockchain-based applications
&lt;/h2&gt;

&lt;p&gt;Here we are dealing with ordinary Web and Mobile applications, in which one of the functions is either to read something from the blockchain network or to write some data to it.&lt;/p&gt;

&lt;p&gt;Communication with the blockchain on the backend side takes place through API requests. Often this is not an HTTP REST API but something more specific like gRPC.&lt;/p&gt;

&lt;p&gt;The API can be either a third-party system or just a node of the blockchain network located inside the system.&lt;/p&gt;

&lt;p&gt;What we test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;integration with blockchain&lt;/li&gt;
&lt;li&gt;functional and non-functional application properties (as at any other application)&lt;/li&gt;
&lt;li&gt;security and performance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pay attention that the application's performance can depend on how fast blockchain works at the backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cryptowallets
&lt;/h2&gt;

&lt;p&gt;Wallets are applications that store information about your passwords and enable you to buy and sell cryptocurrency. They can be both in the form of web and mobile applications as well as desktop.&lt;/p&gt;

&lt;p&gt;The main aspect when testing is the use of test blockchain networks (TESTNET) for transactions. The currency is technically the same as the real one in such networks, but it costs nothing.&lt;/p&gt;

&lt;p&gt;In addition, there may also be specific types of wallets in individual electronic devices. And this is a separate exciting world of embedded devices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Smart contracts
&lt;/h2&gt;

&lt;p&gt;Smart contracts are software code (uploaded to the blockchain) that implements some business logic. Most often, smart contracts mean the code in the Solidity language in the Ethereum blockchain. But there are other programming languages available in different blockchains.&lt;/p&gt;

&lt;p&gt;What we test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;unit tests for contracts&lt;/li&gt;
&lt;li&gt;functional tests contracts&lt;/li&gt;
&lt;li&gt;security testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The unusual thing about testing is that it starts working immediately after the code gets to the blockchain (“deployed to production”). It is challenging to "stop" it. And it’s impossible to delete or revert the deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cryptocurrency exchanges
&lt;/h2&gt;

&lt;p&gt;Exchanges are usually web (or mobile) applications that allow you to create an account and trade (convert) different cryptocurrencies.&lt;/p&gt;

&lt;p&gt;They are very similar to ordinary sites for banking or currency exchanges.&lt;/p&gt;

&lt;p&gt;The main difficulty of testing here is integration with APIs of many hundreds (or even thousands) of blockchains. So get ready for integration bugs and quick fixes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What do you need to know and understand to test the blockchain?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Hashing: how does it work, and what are the different algorithms for it&lt;/li&gt;
&lt;li&gt;Cryptography: symmetric and asymmetric, electronic signatures&lt;/li&gt;
&lt;li&gt;Consensus protocols and their types&lt;/li&gt;
&lt;li&gt;Distributed systems and methods of communication between a node in a network&lt;/li&gt;
&lt;li&gt;Transaction models: UTxO (Bitcoin) or account-based (Ethereum)&lt;/li&gt;
&lt;li&gt;What are the transactions, and how are they stored (hello Merkle trees :))&lt;/li&gt;
&lt;li&gt;Types of blockchains (Mainnet vs. Testnet, open and permissioned)&lt;/li&gt;
&lt;li&gt;Types of crypto wallets and principles of their work&lt;/li&gt;
&lt;li&gt;Smart contracts (why are they needed)&lt;/li&gt;
&lt;li&gt;Programming languages ​​of smart contracts - Solidity, Plutus, etc&lt;/li&gt;
&lt;li&gt;Tools for local deployment of blockchains for testing&lt;/li&gt;
&lt;li&gt;Smart contract testing tools&lt;/li&gt;
&lt;li&gt;Vulnerabilities and problems of blockchains and smart contracts in particular&lt;/li&gt;
&lt;li&gt;API testing (HTTP REST, gRPC, etc.)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;The world of blockchain is vast and continues to grow. It is not easy to get an initial knowledge about the topic because it is a mix of different areas: distributed systems, cryptography, finance, and others.  &lt;/p&gt;

&lt;p&gt;As there are not so many tools for testing blockchains, you may need to dig through a lot of whitepapers to get specific knowledge. And here is the beauty of blockchain (IMHO) - a short way from academic papers to the real-world implementation of the new concepts.  &lt;/p&gt;

&lt;p&gt;If you, like myself, are interested in blockchain testing - I prepared &lt;a href="https://github.com/alexromanov/awesome-blockchain-testing"&gt;a list of resources&lt;/a&gt; about this topic. It is open-source - so feel free to use it and extend it with new blog posts and papers.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>testing</category>
    </item>
    <item>
      <title>Do's and dont's of test automation interview</title>
      <dc:creator>Oleksandr Romanov</dc:creator>
      <pubDate>Mon, 09 Aug 2021 08:07:11 +0000</pubDate>
      <link>https://dev.to/al8xr/do-s-and-dont-s-of-test-automation-interview-186o</link>
      <guid>https://dev.to/al8xr/do-s-and-dont-s-of-test-automation-interview-186o</guid>
      <description>&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@steve3p_0?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Steve Halama&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/interview?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We all participate in job interviews. Not all interviews went well. &lt;br&gt;
This blog post will share a few tips from my experience ( as a candidate and interviewer) on being a little better at test automation interviews. &lt;/p&gt;

&lt;h2&gt;
  
  
  Interviews - Do's
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Do:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;talk about the impact not about the tasks&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think about all your activities in terms of impact on business that you make. &lt;/p&gt;

&lt;p&gt;If you have written 1000 UI tests, but they are flaky and nobody trust them - it is not an success. It is wasted time.&lt;/p&gt;

&lt;p&gt;If you implemented 3 UI tests, integrate them into the build pipeline and the whole team gets a first automated feedback in matter of minutes after deploy - that's a success.&lt;/p&gt;

&lt;p&gt;If you changed the quality "culture" and integrate new type of testing or "post-mortems" without writing a single line of code - it is even better.&lt;/p&gt;

&lt;p&gt;Make your CV in such manner - concentrate on the impact.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;always ask about the project's current stage, what's expected from automation, and the further plans.&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It will help you understand whether the project is well established (and the only thing you will do is to add new or maintain existing cases) or it is a new one (so the processes and tools should be created or integrated). &lt;/p&gt;

&lt;p&gt;If there is a proof-of-concept of the framework - ask about the choice of the technologies (and about the freedom to change the technologies).&lt;/p&gt;

&lt;p&gt;It is better to know about the project/product more before joining it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;be ready to question, "Did you implement the automation solution / pipeline / process by yourself?".&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here you need to honest about the answer. If you got help from DevOps or developers - just say about it. &lt;/p&gt;

&lt;p&gt;The candidate can't be a senior test automation engineer if he or she only fixed existing or add new tests (in the existing framework) for 3-5 years in a row. &lt;br&gt;
 . &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;be ready to question, "Why did you do this activity?".&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In one of my interviews, I once asked a candidate how the testing process for the game was done. And the answer was, "Well, I just get a new build, install it and play in it." It is a good answer for a trainee, but not for an engineer with a decade of experience.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ask for feedback after the interview.&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It will help you to get points where you need more attention and practice. &lt;/p&gt;

&lt;p&gt;I know only a few candidates that asked me for a technical feedback. As a result they progressed much faster than other engineers. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;always read the company (job) profile and prepare to interview according to that profile.&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I failed one interview because I did not prepare myself for UI test automation questions (even though the company's leading product was websites and UI web technologies).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;publish some code to Github or participate in open-source projects.&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is an excellent way to build a portfolio of your skills. Don't be shy that your projects or solutions will be too "simple." You can always enhance them after you get more experience. &lt;/p&gt;

&lt;h2&gt;
  
  
  Interviews - Dont's
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Don't:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;do not upload the whole testing framework code on Github&lt;/strong&gt; (specifically including logins, password, connection details of the infrastructure) and share it with the interviewer. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, please remove package names or any other product details from the code. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;do not hesitate to say that you have a bad connection during an interview call.&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I had a screening phone call with a recruiter at one interview, and the connection quality was terrible. I asked, "Can you repeat, please?" again and again. So, as a result - I got a rejection with feedback about my low English level.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;do not say to the interviewer: "I don't know how this piece of code works - I just copied and pasted it from StackOverflow, and it 'magically' worked."&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, it will show that you are an honest person, but from the other side, it will show that you didn't want to understand how the code works.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;do not state ALL technologies you ever touched at work or pet projects in your CV.&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything that you put in your resume - can be asked in the interview.  If you wrote an "Open browser and search at Google" Webdriver test in Ruby, do not say you know Ruby. Keep the list of technologies short. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;do not participate in the interview without a T-shirt :)&lt;/strong&gt; even if the interview is a video call. And always - in video interviews, it is better to turn on the camera.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;do not state that everything should be automated only via UI end-to-end level.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Explore other levels and types of testing and automation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;do not state that tool 'X' or framework 'Y' is the best choice for every possible task at work.&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The products are different; the technologies are different too - so be open to new tools and opportunities.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;do not say that code reviews are only for developers.&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Treat automation code as production one in terms of clarity and quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;It is not a complete list of do's and dont's for the interviews. I know that the more experience you get (as a candidate or interviewer), the more new tips you are collecting. &lt;/p&gt;

&lt;p&gt;Good luck with your interviews!&lt;/p&gt;

&lt;p&gt;Which tips can you add to this list? &lt;/p&gt;

</description>
      <category>testing</category>
      <category>interview</category>
      <category>testautomation</category>
    </item>
    <item>
      <title>Challenges in testing blockchain-based applications</title>
      <dc:creator>Oleksandr Romanov</dc:creator>
      <pubDate>Mon, 02 Aug 2021 06:19:36 +0000</pubDate>
      <link>https://dev.to/al8xr/challenges-in-testing-blockchain-based-applications-lg9</link>
      <guid>https://dev.to/al8xr/challenges-in-testing-blockchain-based-applications-lg9</guid>
      <description>&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@blueskin?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Terry&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/blockchain?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Blockchain and applications
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://blockgeeks.com/guides/what-is-blockchain-technology"&gt;Blockchain&lt;/a&gt; is a linked list of records called blocks.&lt;br&gt;&lt;br&gt;
The blocks are connected using &lt;a href="https://en.wikipedia.org/wiki/Cryptography"&gt;cryptography&lt;/a&gt;: each block contains the previous block's hash and information about current transactions.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OjoK0tH4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x17c4rc8tjulwro6x6l4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OjoK0tH4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x17c4rc8tjulwro6x6l4.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The blocks are immutable to change and are replicated across nodes in the blockchain &lt;a href="https://en.wikipedia.org/wiki/Peer-to-peer"&gt;peer-to-peer&lt;/a&gt; network.  &lt;/p&gt;

&lt;p&gt;The most famous blockchain implementation, for now, is Bitcoin. But blockchain is not limited only to &lt;a href="https://blockgeeks.com/guides/what-is-cryptocurrency/"&gt;cryptocurrencies&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;As blockchain provides immutability, integrity, and transparency, it can store any data, not just transactions. Since the beginning of the &lt;a href="https://bitcoin.org/en/"&gt;Bitcoin&lt;/a&gt; release, many companies are constantly exploring new ways to apply blockchain to the current processes in the world.  &lt;/p&gt;

&lt;p&gt;The creation of &lt;a href="https://blockgeeks.com/guides/smart-contracts"&gt;smart contracts&lt;/a&gt; in &lt;a href="https://ethereum.org/en/"&gt;Ethereum&lt;/a&gt; allowed simulating many business processes on the blockchain in a code (with either manual or automatic execution). As a result, now it is possible to build Blockchain-Based applications that allow communication with a given blockchain to store data, make transactions, or execute smart contracts.  &lt;/p&gt;

&lt;p&gt;All these blockchain applications deal with currency (tokens) or store and keep data on the chain. So we need not only build them but also ensure that the applications work as expected (from functional, performance, and security points of view).  &lt;/p&gt;

&lt;p&gt;In this blog post, I will describe the challenges in testing blockchain-based applications based on my experience and also a tremendous research paper of Chhagan Lal and Dusica Marijan - &lt;a href="https://arxiv.org/pdf/2103.10074.pdf"&gt;"Blockchain Testing: Challenges, Techniques, and Research Directions."&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture and testing
&lt;/h2&gt;

&lt;p&gt;Modern blockchain-based applications do not implement blockchain "from scratch". They typically use blockchain networks as one of the components of the system.  &lt;/p&gt;

&lt;p&gt;Here is the sample architecture diagram of the blockchain-based application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H5AadthO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/93eh5jqmfty1bmnuzo6o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H5AadthO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/93eh5jqmfty1bmnuzo6o.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;According to the diagram, the following components need to be tested:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;unit-testing for business logic&lt;/li&gt;
&lt;li&gt;integration between application and blockchain components (API)&lt;/li&gt;
&lt;li&gt;functional testing of blockchain components (smart contract testing)&lt;/li&gt;
&lt;li&gt;integration between application and data storage layer (API)&lt;/li&gt;
&lt;li&gt;end-to-end testing (UI and API)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Few notes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Integration between application and blockchain network is typically tested via API (REST, gRPC, command-line)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If application developers use an existing blockchain network, they may not test its internals (the same with database systems or messaging libraries).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Smart contracts verification include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;functional testing (whether business logic works as expected)&lt;/li&gt;
&lt;li&gt;performance testing (check execution and time complexity)&lt;/li&gt;
&lt;li&gt;security testing (data protection and vulnerabilities)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;As blockchain and smart contracts is a reasonably new technology, test engineers face with several challenges during testing blockchain-based applications:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;lack of practices&lt;/li&gt;
&lt;li&gt;lack of tools&lt;/li&gt;
&lt;li&gt;immutability&lt;/li&gt;
&lt;li&gt;performance&lt;/li&gt;
&lt;li&gt;dependability&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lack of practices (development and testing)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Knowledge.&lt;/strong&gt; To develop and test blockchain-based applications, engineers need to know about various domains (technical, non-technical, legal). But it is hard to find people with such knowledge on the market. E.g., in our company, test engineers need to know distributed systems, cryptography, blockchain, testing, programming, math, finance.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Variety.&lt;/strong&gt; For now it is almost &lt;a href="https://docs.google.com/spreadsheets/d/1OO06RZ7vw8-Hij8ZxB68FaRYRtQEz3GifnLDNwW8sTs/edit#gid=1051902784"&gt;40 different blockchains&lt;/a&gt; available on the market. You can't just "learn" one blockchain: there is an ecosystem of tools for each particular blockchain. Some blockchains use well-known programming languages like C++, Go, Javascript or Java for implementing smart contracts. Another - use their unique programming languages (&lt;a href="https://docs.soliditylang.org/en/v0.8.6/"&gt;Solidity&lt;/a&gt; for Ethereum or &lt;a href="https://plutus.readthedocs.io/en/latest/plutus/tutorials/plutus-playground.html"&gt;Plutus&lt;/a&gt; for Cardano) - so you need to learn them too.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Standards.&lt;/strong&gt; Additionally, there is a lack of guiding procedures, standards, or strategies in designing, developing, and testing blockchain-based applications&lt;/p&gt;

&lt;h2&gt;
  
  
  Lack of tools
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Libraries&lt;/strong&gt;. As there are many programming languages for smart contracts - there is a lack of mature debugging / testing tools for these languages.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automation&lt;/strong&gt;. If you want to ensure that the application works as expected, you need to test the components (in isolation) and system (as a whole). Currently, there is a lack of deployment and automation tools, which allow to deploy and configure blockchain in a "test mode" within one machine's boundaries.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Environment configuration&lt;/strong&gt; takes a lot of time. So the only thing now is to download the full node locally, synchronize it with other nodes and then test it via command-line or API. As a result, the configuration takes an enormous amount of time. If your application uses some wallet functionality, you also need to download and configure it. &lt;/p&gt;

&lt;h2&gt;
  
  
  Immutability
&lt;/h2&gt;

&lt;p&gt;The blockchain is an immutable and open data structure (unless it is not a permissioned one). So as soon as any change is deployed to the network, you can't reverse it back.&lt;br&gt;&lt;br&gt;
Seriously. All the test data will remain on the chain forever :).&lt;br&gt;&lt;br&gt;
Moreover, the test data can be seen by any person via transaction explorers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test data&lt;/strong&gt; need special care as it is available in a public blockchain. Make sure that you don't use any sensitive information in tests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Validate smart contracts&lt;/strong&gt; more and more before deploying them to the chain. Any error that slipped to the contract after the deployment can't be fixed easily - in some cases, you need to create another contract to send money back to the failed accounts (or even change the whole network after a hacking attack).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can't delete the data from the chain.&lt;/strong&gt; So, if your application needs to follow GDPR (&lt;a href="https://gdpr.eu/right-to-be-forgotten/"&gt;right-to-be-forgotten&lt;/a&gt; in particular), you need to consider which data to store.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;The performance of the blockchain-based application is highly tied with the performance of the blockchain components themselves. Some blockchains have a limited latency and rate of input transactions, so they need to be considered in the overall testing strategy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transaction validation&lt;/strong&gt; time depends on a particular chain's consensus protocols - in some cases, it can take minutes or even more for storing one piece of data. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-world&lt;/strong&gt; blockchain workloads are hard to predict due to volatility in blockchain popularity, hacking attacks, and other events.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependability
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Fault-injections&lt;/strong&gt; is a powerful technique in testing highly distributed systems. But due to the dispersed nature of the blockchain systems, it is hard to separate between system level, network level, and user-level fault loads. So there is a lack of tools in this area - mainly because each blockchain has its APIs and components. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Blockchain-based applications give a new set of challenges to the testing world. You need a whole lot of knowledge and skills.  &lt;/p&gt;

&lt;p&gt;But no worries. Imagine, somewhere like 20 years ago, nobody knows how to implement automated tests for web and mobile. There were times when Selenium Webdriver or Appium does not exist. &lt;/p&gt;

&lt;p&gt;If we, as testers, want to succeed in the blockchain world and bring quality "to the table," - we need to dig into technical aspects of the systems and apply known (and maybe yet unknown) testing techniques and tools. &lt;/p&gt;

&lt;p&gt;We will explore functional, performance, and security challenges and tools in more detail in the following posts.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>Automation In Scala: Publish Allure reports with Github Actions</title>
      <dc:creator>Oleksandr Romanov</dc:creator>
      <pubDate>Mon, 19 Jul 2021 09:57:41 +0000</pubDate>
      <link>https://dev.to/al8xr/automation-in-scala-publish-allure-reports-with-github-actions-5g4l</link>
      <guid>https://dev.to/al8xr/automation-in-scala-publish-allure-reports-with-github-actions-5g4l</guid>
      <description>&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@markusspiske?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Markus Spiske&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/report?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In one of the &lt;a href="https://alexromanov.github.io/2021/05/17/scala-allure-report/"&gt;previous blog posts&lt;/a&gt;, I showed how to add Allure reporting to the Scala-based automation project.  &lt;/p&gt;

&lt;p&gt;But generating reports only on the local machine is not enough. The main goal of test reports is to notify the team and the management about the issues found by automated tests.  &lt;/p&gt;

&lt;p&gt;That's why it is essential to share the reports using some notification channels. The channels can be various: emails, Slack or Skype notifications, etc.  &lt;/p&gt;

&lt;p&gt;In this blog post, I will continue my talk about Allure reporting: we will generate reports, push them to the server and notify users about test run results via email.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Build and test with Github Actions
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/features/actions"&gt;Github Actions&lt;/a&gt; is a set of predefined steps for automating CICD workflow for the project. It is defined in simple YAML format.  &lt;/p&gt;

&lt;p&gt;Action can have one or more triggers: on push, pull request for a particular branch. Special triggers allow to run jobs manually (workflow_dispatch) or after getting a special event from another repository (repository dispatch).  &lt;/p&gt;

&lt;p&gt;In our case, we will add a trigger for running workflow by manual execution.&lt;br&gt;
Just add .github/workflows folder structure at the root of the project and add a new .yml file with the description of the flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Execute Test Run&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up JDK&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-java@v1.4.3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;java-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;11.0.8'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Compile&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sbt compile&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;sbt "testOnly * -- -n Smoke"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we define test job for our project that will be executed on ubuntu build machine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it will perform checkout for branch&lt;/li&gt;
&lt;li&gt;then, it will add JDK to build machine&lt;/li&gt;
&lt;li&gt;then it will compile the project and execute the tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As we use &lt;a href="https://www.scala-sbt.org/"&gt;sbt&lt;/a&gt; as a build tool, then we run test job with filter for specific tests&lt;/p&gt;

&lt;h2&gt;
  
  
  Allure server setup
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/kochetkov-ma/allure-server"&gt;Allure server&lt;/a&gt; is an open-source solution for hosting test reports.  &lt;/p&gt;

&lt;p&gt;You can download the project from GitHub and execute it on the local machine, but the best case is to have a dedicated server for reports - e.g., some instance in the cloud.&lt;/p&gt;

&lt;p&gt;For configuration, you need to download &lt;a href="https://hub.docker.com/r/kochetkovma/allure-server"&gt;Docker image&lt;/a&gt; and start the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
docker pull kochetkovma/allure-server:latest
docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 kochetkovma/allure-server:latest

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

&lt;/div&gt;



&lt;p&gt;After you start the server, it will be available at &lt;a href="http://127.0.0.1:8080"&gt;http://127.0.0.1:8080&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gnoMkLUm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8tskkboqvab7vxnkxdx2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gnoMkLUm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8tskkboqvab7vxnkxdx2.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ensure that the Allure server is accessible for calls from Github, as we will call server API for saving reports.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Reports publishing
&lt;/h2&gt;

&lt;p&gt;We will use &lt;a href="https://github.com/Xotabu4/send-to-allure-server-action"&gt;github action from @Xotabu4&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S08cyP9u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/spqwp89ghsyt3eciq81w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S08cyP9u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/spqwp89ghsyt3eciq81w.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Under the hood, this Github action will make an archive from the allure-results folder and store it at the Allure server.&lt;br&gt;&lt;br&gt;
As a result, this action will return the URL to generated report, stored on the server.  &lt;/p&gt;

&lt;p&gt;If you want to use the report URL in further steps (e.g., notification), please add an id property to the action with some name.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Email notification
&lt;/h2&gt;

&lt;p&gt;Email notification is executed via &lt;a href="https://github.com/dawidd6/action-send-mail"&gt;action-send-mail&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;Here is an example of action configuration:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bV9d-Z6B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2firqmzkwdy9djrl3d8w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bV9d-Z6B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2firqmzkwdy9djrl3d8w.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Few notes:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Username and password for connecting to Gmail should be added as SECRETS for repository&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As email action connects to Gmail for sending emails - make sure that &lt;a href="https://alexromanov.github.io/2021/05/04/scala-mail-testing/"&gt;security policies allow&lt;/a&gt; to do it for external resources&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can use Allure report URL from the previous action as steps.allure-report.outputs.report-URL&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Date variable from Get-Date step is used as steps.date.outputs.date&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Recipients are configured as a comma-separated list&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Subject of the email notification will include date and time of the test run. In order to get it, we will use special action:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--muxj5Hjb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bi31todda3601mkr3unp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--muxj5Hjb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bi31todda3601mkr3unp.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Executing action
&lt;/h2&gt;

&lt;p&gt;Navigate to Your repo on Github / Actions tab, select "Execute Test Run" workflow and click Run Workflow.&lt;/p&gt;

&lt;p&gt;As a result, you will get an email with a link to the Allure report (saved on the Allure server).&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;As you can see, Github Actions allow the creation of automated testing workflow in less than 50 lines of code.  &lt;/p&gt;

&lt;p&gt;If your end-to-end tests are a part of the solution - add these actions into the workflow.  &lt;/p&gt;

&lt;p&gt;If your tests are stored in a separate project - you can use &lt;a href="https://docs.github.com/en/actions/reference/events-that-trigger-workflows#repository_dispatch"&gt;repository_dispatch&lt;/a&gt; for subscribing to events from other repositories in the build pipeline.&lt;/p&gt;

&lt;p&gt;You can find the source code of the action at the &lt;a href="https://github.com/alexromanov/scala-automation-samples/blob/main/.github/workflows/manualtestrun.yml"&gt;repository&lt;/a&gt;&lt;/p&gt;

</description>
      <category>automation</category>
      <category>testing</category>
    </item>
    <item>
      <title>Should You Use Contract Testing?</title>
      <dc:creator>Oleksandr Romanov</dc:creator>
      <pubDate>Mon, 12 Jul 2021 09:53:02 +0000</pubDate>
      <link>https://dev.to/al8xr/should-you-use-contract-testing-26jh</link>
      <guid>https://dev.to/al8xr/should-you-use-contract-testing-26jh</guid>
      <description>&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@cytonn_photography?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Cytonn Photography&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/contract?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Almost any tester involved in testing microservices-based systems has heard about the magic contract testing.  &lt;/p&gt;

&lt;p&gt;But what exactly are contract tests? Should you use it in your project?  &lt;/p&gt;

&lt;p&gt;In this blog post, I will talk about the case when contract testing can help. I will also compare contract testing with other types of tests and share my thoughts on using contracts in your application. &lt;/p&gt;

&lt;h2&gt;
  
  
  The story
&lt;/h2&gt;

&lt;p&gt;Let me introduce two characters of our story: Dave (The Developer) and Tina (The Tester). Both of them work in one Scrum team delivering a critical piece of software for a conference application. The whole backend contains hundreds of microservices.  &lt;/p&gt;

&lt;p&gt;Their task is to provide the functionality to get bonuses for a given user. Dave needs to implement a new API call from the User Conference service to the Bonus Conference service to retrieve the bonus data for users.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eSS1B5fu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aouyz9383pj1awrpnzbb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eSS1B5fu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aouyz9383pj1awrpnzbb.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The developer way
&lt;/h2&gt;

&lt;p&gt;As a good developer, Dave wants to cover new functionality with tests. The best possible way to do it - is unit testing.  &lt;/p&gt;

&lt;p&gt;So Dave implements many unit tests for checking feature functionality on the User Conference Service. All external calls to Bonus Conference service or any other resource are mocked (so Dave is responsible for defining the response values).  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pqeok1c2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kebtb5v6ymovokll3yzv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pqeok1c2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kebtb5v6ymovokll3yzv.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dave creates more and more unit tests; the code coverage tool says that it is covered more than 80% of the new code.  &lt;/p&gt;

&lt;p&gt;Dave finishes his work with the confidence that the tests catch-all error cases and bugs. All tests are executed locally within seconds.  &lt;/p&gt;

&lt;h2&gt;
  
  
  The tester way
&lt;/h2&gt;

&lt;p&gt;After Dave's change is deployed to the staging environment, Tina starts the testing. And it turns out that the new functionality does not work at all.  &lt;/p&gt;

&lt;p&gt;The root cause of the problem is that another developer changed the Bonus Conference service API, and Dave was not aware of it at all. All unit tests check the service with the older version of the API.  &lt;/p&gt;

&lt;p&gt;Tina, as a tester, catches the broken change only after end-to-end testing of the functionality.&lt;br&gt;
After the root cause analysis, Dave and Tina decide to cover the broken case by end-to-end automated test. It will detect the broken API issue when the User Conference service will be deployed to the test environment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CUBtl2lb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z6xtztnd79tl7qlgw7vn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CUBtl2lb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z6xtztnd79tl7qlgw7vn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So from the one hand, Dave has many unit tests that provide good coverage, fast feedback, and runs on a local machine.  &lt;/p&gt;

&lt;p&gt;On the other hand, the end-to-end test will provide an additional check of broken integration, but the feedback time will be slow: all services must be deployed to the test environment first.  &lt;/p&gt;

&lt;p&gt;Given the number of services (hundreds) and updates per day (thousands or more) - each developer should wait for an entire deployment to find the end-to-end test results.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maybe there is another way of getting information about broken integration? It turns out that it exists.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Contract testing to the rescue!
&lt;/h2&gt;

&lt;p&gt;Contract testing is another approach to test integration between two counterparties.  &lt;/p&gt;

&lt;p&gt;These two sides can be services (communicates via HTTP REST, messaging, or gRPC calls), client and server, various third parties.  &lt;/p&gt;

&lt;p&gt;In contract testing terminology, the side that makes the request is called the &lt;strong&gt;&lt;em&gt;Consumer&lt;/em&gt;&lt;/strong&gt;; the side that responds is called the &lt;strong&gt;&lt;em&gt;Producer&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TJPMNCId--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fvfptv0a7pr4ahyslm7c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TJPMNCId--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fvfptv0a7pr4ahyslm7c.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The main idea of contract testing is to provide fast information about broken integration without deploying services to the environment. Imagine it like an end-to-end test that delivers the results with a speed of unit test.  &lt;/p&gt;

&lt;p&gt;Instead of creating separate unit tests on the User Conference and Bonus conference services, Dave will start with the contract definition.  &lt;/p&gt;

&lt;p&gt;The contract defines what the User Conference service will request and what it expects to get in response.  &lt;/p&gt;

&lt;p&gt;Here is an example of the contract, using &lt;strong&gt;&lt;a href="https://spring.io/projects/spring-cloud-contract"&gt;Spring Cloud Contract&lt;/a&gt;&lt;/strong&gt; library:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TJPMNCId--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fvfptv0a7pr4ahyslm7c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TJPMNCId--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fvfptv0a7pr4ahyslm7c.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then both services should implement contract tests for each contract. After contract tests are implemented, the most exciting part begins.  &lt;/p&gt;

&lt;p&gt;If the developer wants to change to Bonus Conference service API (the Producer), he needs to change a contract. Otherwise, the Bonus Conference service will not be built and compiled locally due to failed contract tests.  &lt;/p&gt;

&lt;p&gt;After the developer changes the contract, all consumers will be notified about the change. So they need either approve the change (handle it in their services) or comment that this change breaks the integration.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Test types analysis
&lt;/h2&gt;

&lt;p&gt;Let's compare three types of tests: unit, contract, and end-to-end API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cLK8KRpA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ygm5flrxh1ercnjgg64e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cLK8KRpA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ygm5flrxh1ercnjgg64e.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Execution.&lt;/strong&gt; Unit and contract tests are executed locally on the developer's or build machine, but end-to-end tests require services to be deployed to some dedicated environment.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Feedback time.&lt;/strong&gt; Feedback time of failed tests is fast for unit and contract tests. Of course, contract tests require additional seconds to generate tests from contracts, but the overall execution time is almost like for unit tests. As for end-to-end tests, we need to &lt;strong&gt;wait&lt;/strong&gt;: wait for service to build and compile; wait for services unit and contract tests execution; wait for the deployment of the services to environment; wait for test execution.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Setup complexity.&lt;/strong&gt; For writing unit tests, you need to include a unit-testing library in the project, and you are ready to go. In case of contract tests, you need to set a contract test repository and build an automatic workflow for consumers and producers. For end-to-end tests, you need to develop a deployment pipeline and tests themselves.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Change tolerance.&lt;/strong&gt; Unit tests are build only on one developer's assumption on how another service should work in a given moment. If something is changed, unit tests will always be "green." On the contrary, contract and end-to-end tests will fail in case of broken integration changes happen.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Functionality verification.&lt;/strong&gt; Both unit and end-to-end tests verify functionality. The main goal of contract tests is to check only the format of communication between two parts.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Team collaboration.&lt;/strong&gt; To implement unit tests, the developer does not need to communicate with other developers. Contract and end-to-end tests push the developer to communicate and to think about the impact of changes.  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Should I use contract testing?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Contract tests are not a substitution to the unit or end-to-end tests.&lt;/strong&gt; It is just one type of test that can be performed.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eJSGP3qw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/heoxef0w105a4k4ksjh6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eJSGP3qw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/heoxef0w105a4k4ksjh6.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If contract testing workflow is implemented correctly - &lt;strong&gt;&lt;em&gt;it is possible to minimize end-to-end tests and speed up the development process.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So the crucial question remains: &lt;strong&gt;"Should I use contract testing?"&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;You will not get a value from the contract testing if: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the coverage of unit tests is low&lt;/li&gt;
&lt;li&gt;the number of end-to-end tests is close to zero&lt;/li&gt;
&lt;li&gt;there is a lack of skills for setting up the project and writing the contracts&lt;/li&gt;
&lt;li&gt;there is a lack of dedication to change a process of delivery&lt;/li&gt;
&lt;li&gt;the communication between teams is broken (e.g., blaming each other for integration issues) &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Contract tests are not a "silver bullet" which provides only the benefits.  &lt;/p&gt;

&lt;p&gt;It requires many efforts for configuration; it requires even more efforts to change the developer "culture." With contract tests, you can't make hidden changes, silently push it and close the Jira as soon as possible.  &lt;/p&gt;

&lt;p&gt;And most important: contract testing forces you to think more about the consequences of each change that goes to production.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Have you already tried contract testing for your projects? Did you get any benefits?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>automatedtesting</category>
      <category>microservices</category>
      <category>contracttesting</category>
    </item>
    <item>
      <title>Modern Problems With Test Automation</title>
      <dc:creator>Oleksandr Romanov</dc:creator>
      <pubDate>Mon, 05 Jul 2021 12:40:48 +0000</pubDate>
      <link>https://dev.to/al8xr/modern-problems-with-test-automation-1bj</link>
      <guid>https://dev.to/al8xr/modern-problems-with-test-automation-1bj</guid>
      <description>&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@kxvn_lx?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;kevin laminto&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/cyberpunk?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Brave new world
&lt;/h2&gt;

&lt;p&gt;Test automation is everywhere. Almost every job description in the software testing industry requires knowledge of programming and automation at some point.&lt;br&gt;&lt;br&gt;
If you don't have these skills - please go to numerous courses and learn the skills. Now, as soon as possible.&lt;br&gt;&lt;br&gt;
Otherwise, you will not get a good job. Or you will not be promoted. Or you will not be an SDET (Software Developer In Test).  &lt;/p&gt;

&lt;p&gt;But do we get the value from test automation? Do we correctly implement automated tests for our projects? Are there any problems with that?  &lt;/p&gt;

&lt;p&gt;In this blog post, I want to highlight a few problems with test automation. Some of the issues I faced personally, other - I know by talking to other engineers.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Don't want to see the trees for the forest
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Concentrating only on the UI/API end-to-end level.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"If they want test automation, we will create a bunch of UI end-to-end tests and get immediate results! Everybody will be happy! Bugs will not slip into the release!"  &lt;/p&gt;

&lt;p&gt;"Let's use this new fancy record-and-playback tool, and we will be able to create automated tests even without programming knowledge."  &lt;/p&gt;

&lt;p&gt;"Let's use BDD (Behaviour Driven Development) approach, and the team will create end-to-end UI tests which business people and developers will use! I have not asked them yet, but they will use these tests for sure!"  &lt;/p&gt;

&lt;p&gt;"Unit, component, integration tests... Oh, boy! It is too technical, and I am not a developer! I want to fix UI tests day by day."  &lt;/p&gt;

&lt;p&gt;"I heard at the conference that this tool is popular, so I purchased a license for a year! Now we as a team need to find out how we can use it."  &lt;/p&gt;

&lt;p&gt;"Our UI automated tests are green - why do we still have bugs?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Thinking fast and small
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Implementing quick and destructive solutions, and then moving to the next project.&lt;/strong&gt;  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Now I am going to implement a test framework with this fancy new library X and move to another project ASAP!"  &lt;/p&gt;

&lt;p&gt;"If I use this new library that just been released a month ago - I will be able to put it into my CV and request more salary!"  &lt;/p&gt;

&lt;p&gt;"Who cares that for test execution, you need first to install a hundred dependencies, update 39 different files, and re-compile half of the product?"  &lt;/p&gt;

&lt;p&gt;"Why should I write README for the test project? Anyone can understand the solution and quickly start implement the tests!"  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Scratching a technology surface
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Lack of focus on deep technology and architecture knowledge.&lt;/strong&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I don't know how the system work - for me, it is only a set of web pages or mobile app which is somehow works (by magic)."  &lt;/p&gt;

&lt;p&gt;"Subsystems, abstractions, load-balancers, HTTP calls, messaging, replication? Wow - it is too much for me. I will write the "Open Google page" test one more time using a bright and shiny new framework."  &lt;/p&gt;

&lt;p&gt;"Wow, I just clicked something, got some scary error, make a screenshot and throw it to the developer."  &lt;/p&gt;

&lt;p&gt;"Why has a bug happened? How can we prevent it? - Oh, I don't know, the developer did a fix, and now it works. Somehow. I don't care."  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  So what?
&lt;/h2&gt;

&lt;p&gt;For junior test automation engineers, it is entirely normal to ask all of such questions. It is normal to concentrate on the UI tests only, do not understand bug stack traces, and do not dig into the technology.  &lt;/p&gt;

&lt;p&gt;But if you are a senior engineer now and still see many such questions asked, here is what we can do to make the situation a little better.  &lt;/p&gt;

&lt;p&gt;Here what you can do:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Learn the programming language and technology stack of the system you are working with.&lt;/strong&gt; Which framework do developers use, which database? How is the system deployed? How is your data replicated across the system? What are third parties to an application under test? The more you know how the system works, the faster you can investigate and fix the failures. And the better tests you can create.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Investigate more about different levels of testing: unit, component, integration, contract.&lt;/strong&gt; What are their pros and cons? Why can't you use such tests in your project? What blocks you from adding such tests?  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Discover the root causes of the issues together with developers and DevOps engineers.&lt;/strong&gt; Is it possible to find the bug before the UI tests caught it? Which actions can you do now to prevent such issues in the future? Where do you have "holes" in code coverage? &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Do not consider your job as a "fast fire-and-forget consultancy. (Unless you are a consultant)"&lt;/strong&gt; Always ask stakeholders why they need to have test automation. Which value do they want to get from such tests? How can you help them to release faster and more reliable? What is the product vision for upcoming years, and how automation fits in?  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Explore how other companies solve issues with test flakiness, stability, scalability.&lt;/strong&gt; In most cases, your application is not a unique - so you can find out that your current struggles have already been solved by some open-source tool that you can use.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Do not try to use every fancy tool on the market.&lt;/strong&gt; Start with careful evaluation and compare different tools in the segment. Do not believe that automated tests can be recorded once and be executed forever. Maintenance always matters!  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Always think about which impact do your engineering efforts make on the product.&lt;/strong&gt; Is it make the life of other developers easier? Does it help to investigate issues faster?   &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Every team member can be a source of automation problems. Maybe it is a test manager who wants to change a process and tools. Perhaps it is a developer who doesn't like to share information on how the product works internally. Or it can be a test automation engineer who wants quick results without any effort.  &lt;/p&gt;

&lt;p&gt;Anyway, it is up to you to identify and fix such problems. Good luck in fixing it!  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Have you ever faced any of these problems?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>automation</category>
    </item>
    <item>
      <title>Getting Started With Testing Microservices</title>
      <dc:creator>Oleksandr Romanov</dc:creator>
      <pubDate>Mon, 28 Jun 2021 07:38:17 +0000</pubDate>
      <link>https://dev.to/al8xr/getting-started-with-testing-microservices-95l</link>
      <guid>https://dev.to/al8xr/getting-started-with-testing-microservices-95l</guid>
      <description>&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@ryoji__iwata?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Ryoji Iwata&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/pieces?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Microservices testing: from the theory to practice
&lt;/h2&gt;

&lt;p&gt;In this blog post, I will share resources that help you to be more prepared to testing microservices-based systems.  &lt;/p&gt;

&lt;p&gt;My background is Java and Spring Boot. Many tools and libraries that I will share are from the Java world. But you can find analogies in other technology stacks as well. &lt;/p&gt;

&lt;p&gt;I will split resources into the following sections - from the theory to practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learn the basics&lt;/li&gt;
&lt;li&gt;Explore technology stack&lt;/li&gt;
&lt;li&gt;Build test strategy&lt;/li&gt;
&lt;li&gt;Learn tools&lt;/li&gt;
&lt;li&gt;Investigate contract testing&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Learn the basics
&lt;/h2&gt;

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

&lt;p&gt;The first thing is to understand microservices architecture and how it differs from more traditional monolith systems.&lt;/p&gt;

&lt;p&gt;The following resources will help you to build initial information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.amazon.com/Building-Microservices-Designing-Fine-Grained-Systems/dp/1491950358" rel="noopener noreferrer"&gt;Building Microservices&lt;/a&gt;&lt;/strong&gt; book by Sam Newman&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://youtu.be/j3XufmvEMiM" rel="noopener noreferrer"&gt;What are microservices&lt;/a&gt;&lt;/strong&gt; video by freeCodeCamp&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://martinfowler.com/articles/microservices.html" rel="noopener noreferrer"&gt;Microservices overview&lt;/a&gt;&lt;/strong&gt; by Martin Fowler&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.ibm.com/cloud/learn/microservices" rel="noopener noreferrer"&gt;Microservices&lt;/a&gt;&lt;/strong&gt; at IBM Cloud&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://medium.com/hashmapinc/the-what-why-and-how-of-a-microservices-architecture-4179579423a9" rel="noopener noreferrer"&gt;The What, Why, and How of a Microservices Architecture&lt;/a&gt;&lt;/strong&gt; by Jetinder Singh&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Explore technology stack
&lt;/h2&gt;

&lt;p&gt;Resources (Spring Boot):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://spring.io/projects/spring-boot" rel="noopener noreferrer"&gt;Spring Boot&lt;/a&gt;&lt;/strong&gt; - project documentation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.udemy.com/course/spring-boot-intro/" rel="noopener noreferrer"&gt;Learn Spring Boot - Rapid Spring Application Development&lt;/a&gt;&lt;/strong&gt; course on Udemy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://docs.spring.io/spring-framework/docs/current/reference/html/testing.html" rel="noopener noreferrer"&gt;Spring Test&lt;/a&gt;&lt;/strong&gt; library overview&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://spring.io/guides/gs/testing-web/" rel="noopener noreferrer"&gt;Testing WEB APIs&lt;/a&gt;&lt;/strong&gt; at Spring Boot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of you extensively use virtualization tools, like Docker - learn it.&lt;br&gt;&lt;br&gt;
Pay attention to how to start a single microservice in Docker container on your local machine (together with its dependencies: SQL, NoSQL databases, messaging systems, etc.):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://dzone.com/articles/advanced-functional-testing-in-spring-boot-by-usin" rel="noopener noreferrer"&gt;Advanced Functional Testing in Spring Boot Using Docker in Tests&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://mydeveloperplanet.com/2020/05/05/easy-integration-testing-with-testcontainers/" rel="noopener noreferrer"&gt;Easy Integration Testing With Testcontainers&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are not from the Java world - ask your fellow developers about technologies and frameworks they use for building microservices in your organization.&lt;br&gt;&lt;br&gt;
Do not hesitate to ask which testing tools, practices, and guidelines they already use.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Build test strategy
&lt;/h2&gt;

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

&lt;p&gt;Classic approach with unit, integration, and end-to-end testing can't be applied to microservices "as is." That's why approaches to testing need to be reworked and adapted.&lt;/p&gt;

&lt;p&gt;Resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://martinfowler.com/articles/microservice-testing/" rel="noopener noreferrer"&gt;Testing Strategies in a Microservice Architecture&lt;/a&gt;&lt;/strong&gt; by Toby Clemson&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://martinfowler.com/articles/practical-test-pyramid.html" rel="noopener noreferrer"&gt;The Practical Test Pyramid&lt;/a&gt;&lt;/strong&gt; by Ham Vocke&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.infoq.com/articles/twelve-testing-techniques-microservices-intro/" rel="noopener noreferrer"&gt;Testing Microservices: an Overview of 12 Useful Techniques&lt;/a&gt;&lt;/strong&gt; by Wojciech Bulaty and Liam Williams&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://copyconstruct.medium.com/testing-microservices-the-sane-way-9bb31d158c16" rel="noopener noreferrer"&gt;Testing Microservices, the sane way&lt;/a&gt;&lt;/strong&gt; - very big and highly informative article by Cindy Sridharan&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.slideshare.net/chris.e.richardson/oracle-codeone-2019-descending-the-testing-pyramid-effective-testing-strategies-for-microservices" rel="noopener noreferrer"&gt;Descending the Testing Pyramid: Effective Testing Strategies for Microservices&lt;/a&gt;&lt;/strong&gt; slides by Chris Richardson
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Learn tools
&lt;/h2&gt;

&lt;p&gt;Tools and libraries can greatly simplify testing and automation and boost developer productivity.  &lt;/p&gt;

&lt;p&gt;Resources:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="http://wiremock.org/" rel="noopener noreferrer"&gt;Wiremock&lt;/a&gt;&lt;/strong&gt; for mocking external API (API virtualization)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://swagger.io/" rel="noopener noreferrer"&gt;Swagger&lt;/a&gt;&lt;/strong&gt; for API visualization, research, and testing. Ideally, each microservices should provide an API for public and admin usage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.baeldung.com/java-in-memory-databases" rel="noopener noreferrer"&gt;In-memory databases&lt;/a&gt;&lt;/strong&gt; will help you to prepare service dependencies faster and make them more reliable for unit testing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.testcontainers.org/" rel="noopener noreferrer"&gt;Testcontainers&lt;/a&gt;&lt;/strong&gt;. The incredible library automatically runs service dependencies (databases, messaging, other services) in a separate docker containers. As a result, you will have a "real-world" setup for service component tests - but with much more control over dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://rest-assured.io/" rel="noopener noreferrer"&gt;Rest Assured&lt;/a&gt;&lt;/strong&gt; for API test automation. It is just one of the possible tools: do not hesitate to try something else and find a tool suitable for particular purposes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Investigate contract testing
&lt;/h2&gt;

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

&lt;p&gt;When the number of microservices is increasing to hundreds or thousands, the problems of integration arises:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;if I deploy this API change - which microservices will I break?&lt;/li&gt;
&lt;li&gt;which services depend on each other?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Contract testing allows building another layer of fast and reliable tests, preventing integration issues as soon as possible in the development workflow.&lt;/p&gt;

&lt;p&gt;Depending on the technologies used on your project, you may prefer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://spring.io/projects/spring-cloud-contract" rel="noopener noreferrer"&gt;Spring Cloud Contract&lt;/a&gt;&lt;/strong&gt;. It works best with Java and Spring ecosystem (but not limited to it)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://pactflow.io/" rel="noopener noreferrer"&gt;PACT tool&lt;/a&gt;&lt;/strong&gt;. It supports multiple programming languages out-of-the-box &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If services use gRPC protocol for communication - &lt;strong&gt;&lt;a href="https://medium.com/@ivangsa/consumer-driven-contract-testing-for-grpc-pact-io-d60155d21c4c" rel="noopener noreferrer"&gt;you can use PACT for contract testing as well&lt;/a&gt;.&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Resources:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://pactflow.io/blog/what-is-contract-testing/" rel="noopener noreferrer"&gt;What is contract testing&lt;/a&gt;&lt;/strong&gt; by PACT developers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.ontestautomation.com/an-introduction-to-contract-testing-part-1-meet-the-players/" rel="noopener noreferrer"&gt;An introduction to contract testing&lt;/a&gt;&lt;/strong&gt; blog post series by Bas Dijkstra&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.youtube.com/watch?v=U05q0zJsKsU&amp;amp;list=PLwy9Bnco-IpfZ72VQ7hce8GicVZs7nm0i" rel="noopener noreferrer"&gt;Introduction to contract testing with Pactflow&lt;/a&gt;&lt;/strong&gt; video series by PACT developers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://youtu.be/_AYfxXJ7o20" rel="noopener noreferrer"&gt;Practical Contract Testing with Spring Cloud Contract&lt;/a&gt;&lt;/strong&gt; - my talk at TestCon Europe&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pluralsight.com/courses/spring-cloud-contract-introduction" rel="noopener noreferrer"&gt;Spring Cloud Contract course&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.youtube.com/watch?v=XRXTsQwyZSU&amp;amp;list=PLt1SIbA8guusAJIBS8JgbSFKfQdVkWDbl" rel="noopener noreferrer"&gt;gRPC course&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Microservices architecture is not a "silver" bullet in software development. The benefits also come with drawbacks.  &lt;/p&gt;

&lt;p&gt;For tester's point of view - &lt;strong&gt;&lt;a href="https://alexromanov.github.io/2018/09/10/microservices-automation-approach/" rel="noopener noreferrer"&gt;testing microservices is like a testing system of systems&lt;/a&gt;&lt;/strong&gt;: you start with single service verification in isolation, then move to integrate it with dependencies and other services, then you move to end-to-end API and UI tests as for any application.  &lt;/p&gt;

&lt;p&gt;The biggest challenge here is that the previously described testing process needs to be applied to many different services. It is not fast and scalable to do it manually - so high investment in automation is a prerequisite to any successful microservices testing effort. &lt;/p&gt;

&lt;p&gt;This list of resources is not complete - it is just the best ones that helped me a lot in the past.  &lt;/p&gt;

&lt;p&gt;What is your favorite book or blog post about microservices?&lt;/p&gt;

</description>
      <category>testing</category>
      <category>microservices</category>
      <category>qa</category>
      <category>automation</category>
    </item>
    <item>
      <title>Automation in Scala: API tests for gRPC service</title>
      <dc:creator>Oleksandr Romanov</dc:creator>
      <pubDate>Mon, 14 Jun 2021 06:32:34 +0000</pubDate>
      <link>https://dev.to/al8xr/automation-in-scala-api-tests-for-grpc-service-4b8e</link>
      <guid>https://dev.to/al8xr/automation-in-scala-api-tests-for-grpc-service-4b8e</guid>
      <description>&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@jannerboy62?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Nick Fewings&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/communication?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is gRPC?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://grpc.io/"&gt;gRPC&lt;/a&gt; - is a modern Remote Procedure Call framework created and popularized by Google but now is under &lt;a href="https://www.cncf.io/"&gt;CNCF&lt;/a&gt; license.  &lt;/p&gt;

&lt;p&gt;The main idea of the framework is to provide for clients, written in various languages, a possibility to execute remote calls to the server as if it is a local call.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lhOz8NMr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qzkruj4rbmzczw8ktkvk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lhOz8NMr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qzkruj4rbmzczw8ktkvk.png" alt="Alt Text"&gt;&lt;/a&gt; Picture from &lt;a href="https://grpc.io/docs/what-is-grpc/introduction/"&gt;grpc.io docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The core concept of gRPC is that all communication between server and client is based on &lt;a href="https://developers.google.com/protocol-buffers/docs/overview"&gt;Protocol Buffers&lt;/a&gt; defined in proto files. The server will implement and support this interface, and the client will generate and use stub code. &lt;/p&gt;

&lt;p&gt;More about gRPC and concepts - &lt;a href="https://grpc.io/docs/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing: Greeter service
&lt;/h2&gt;

&lt;p&gt;gRPC service example is taken from the official &lt;a href="https://doc.akka.io/docs/akka-grpc/current/server/index.html"&gt;akka-grpc guide&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/alexromanov/server-grpc-sample"&gt;server-grpc-example&lt;/a&gt; repository contains a proto file with a service definition and its implementation. You can execute it on a local machine by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sbt runMain io.grpc.examples.helloworld.GreeterClient
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, the server will start at &lt;strong&gt;localhost:8080&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Protobuf definition for the service is the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="na"&gt;syntax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"proto3"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"google/protobuf/timestamp.proto"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;option&lt;/span&gt; &lt;span class="na"&gt;java_multiple_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;option&lt;/span&gt; &lt;span class="na"&gt;java_package&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"example.myapp.example.myapp.helloworld.grpc"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;option&lt;/span&gt; &lt;span class="na"&gt;java_outer_classname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"HelloWorldProto"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;service&lt;/span&gt; &lt;span class="n"&gt;GreeterService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;SayHello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HelloRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HelloReply&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;ItKeepsTalking&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="n"&gt;HelloRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HelloReply&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;ItKeepsReplying&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HelloRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="n"&gt;HelloReply&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;StreamHellos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="n"&gt;HelloRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="n"&gt;HelloReply&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;HelloRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;HelloReply&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;google.protobuf.Timestamp&lt;/span&gt; &lt;span class="na"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, Greeter Service has four methods:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SayHello()&lt;/strong&gt; method for unary calls: a client sends a single request to the server and gets a single response back
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ItKeepsTalking()&lt;/strong&gt; method for client streaming: the client will send a bunch of messages to the server and, after that, will wait for a single reply back&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ItKeepsReplying()&lt;/strong&gt; method for server streaming: the client will read a stream of messages from a server until there are no more new messages.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;StreamHellos()&lt;/strong&gt; method for bi-directional communication: the client and the server send a stream of messages to each other. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Automate by consuming proto files
&lt;/h2&gt;

&lt;p&gt;Test automation process for gRPC based service consists of the following steps:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Add sbt plugin for &lt;a href="https://doc.akka.io/docs/akka-grpc/current/index.html"&gt;Akka gRPC&lt;/a&gt; - create &lt;strong&gt;plugins.sbt&lt;/strong&gt; file with the following content in the &lt;strong&gt;repo/project&lt;/strong&gt; folder.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="nf"&gt;addSbtPlugin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.lightbend.akka.grpc"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s"&gt;"sbt-akka-grpc"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s"&gt;"2.0.0"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add dependencies to &lt;strong&gt;build.sbt&lt;/strong&gt; and update the project.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="nf"&gt;enablePlugins&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AkkaGrpcPlugin&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;libraryDependencies&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;"org.scalatest"&lt;/span&gt; &lt;span class="o"&gt;%%&lt;/span&gt; &lt;span class="s"&gt;"scalatest"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s"&gt;"3.3.0-SNAP2"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nc"&gt;Test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Get all proto files from the &lt;a href="https://github.com/alexromanov/server-grpc-sample"&gt;server&lt;/a&gt; repository. In our case, it will be just copying &lt;a href="https://github.com/alexromanov/server-grpc-sample/blob/main/src/main/protobuf/hello_world.proto"&gt;hello_world.proto&lt;/a&gt; file from server repo and pasting it to src/main/protobuf directory. &lt;/p&gt;

&lt;p&gt;As an improvement, proto files can(and should!) be automatically downloaded from the server or central proto file repository to all client repositories. It prevents the client from synchronization errors as the development of the server functionality evolves.  &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Generate gRPC clients from proto files. As our build system in sbt, you need to execute the command&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sbt compile
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;in Terminal or choose it from sbt command list in IDE. &lt;br&gt;
As a result, all clients generated from proto file can be found at &lt;em&gt;/target/scala-2.13/akka-grpc/main&lt;/em&gt; folder.   &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add &lt;a href="https://www.scalatest.org/user_guide/using_matchers"&gt;Matchers&lt;/a&gt; and &lt;a href="https://docs.scala-lang.org/overviews/core/futures.html"&gt;ScalaFutures&lt;/a&gt; traits to test class definition.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GreeterServiceApiTest&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AnyFlatSpec&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;Matchers&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;ScalaFutures&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure default waiting timeout for responses.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;implicit&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;patienceConfig&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;PatienceConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nc"&gt;PatienceConfig&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Span&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Minutes&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;interval&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Span&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Millis&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add configuration for gRPC client.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;host&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;
&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;port&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;

&lt;span class="k"&gt;implicit&lt;/span&gt; &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;system&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;ActorSystem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ActorSystem&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"api-test"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;clientSettings&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;GrpcClientSettings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;GrpcClientSettings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;connectToServiceAt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;withTls&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;client&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;GreeterService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GreeterServiceClient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clientSettings&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Implement the tests&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="s"&gt;"Greeter Service"&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="s"&gt;"handle unary requests and response"&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getRandomValue&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;response&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;sayHello&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HelloRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;)).&lt;/span&gt;&lt;span class="py"&gt;futureValue&lt;/span&gt;

    &lt;span class="nv"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;getTimestamp&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
    &lt;span class="nv"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;message&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="nf"&gt;be&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="s"&gt;"Hello, $name"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="s"&gt;"Greeter Service"&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="s"&gt;"handle client streaming"&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;data&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getRandomList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;response&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;itKeepsTalking&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Source&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HelloRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="o"&gt;)))).&lt;/span&gt;&lt;span class="py"&gt;futureValue&lt;/span&gt;

    &lt;span class="nv"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;timestamp&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
    &lt;span class="nv"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;message&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="nf"&gt;be&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="s"&gt;"Hello, ${data.mkString("&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;")}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="s"&gt;"Greeter Service"&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="s"&gt;"handle server streaming"&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getRandomValue&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;responses&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;itKeepsReplying&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HelloRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;)).&lt;/span&gt;&lt;span class="py"&gt;runWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Sink&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;seq&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;futureValue&lt;/span&gt;

    &lt;span class="n"&gt;responses&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;empty&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;messages&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;responses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;message&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;toList&lt;/span&gt;
    &lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="s"&gt;"Greeter Service"&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="s"&gt;"handle bi-directional streaming"&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;data&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getRandomList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;responses&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;streamHellos&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Source&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HelloRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="o"&gt;)))).&lt;/span&gt;&lt;span class="py"&gt;runWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Sink&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;seq&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;futureValue&lt;/span&gt;

    &lt;span class="n"&gt;responses&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;empty&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;messages&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;responses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;message&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;toList&lt;/span&gt;
    &lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Pay attention that we can't get a response straight away - we need to wait until Future completes and then get the data by executing &lt;strong&gt;.futureValue&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;Matchers library provides a fluent api for writing assertions - for single values and collections of elements.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Execute the tests either from IDE or from Terminal&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sbt &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Automation of gRPC-based services is a little bit similar to automating &lt;a href="https://wikipedia.org/wiki/SOAP"&gt;SOAP-based&lt;/a&gt; services. In both cases, you have some utilities for generating clients as a code (&lt;strong&gt;ws-consume&lt;/strong&gt; for SOAP and &lt;strong&gt;akka-grpc&lt;/strong&gt; or &lt;strong&gt;scalapb&lt;/strong&gt; for gRPC).  &lt;/p&gt;

&lt;p&gt;After you generate a client - an overall approach is the same as for any API tests - firing a request with test data and asserting responses.  &lt;/p&gt;

&lt;p&gt;gRPC brings a bit more complexity with client, server, and bi-directional streaming - but you can handle it without any problems using futures and collecting all responses in Lists.  &lt;/p&gt;

&lt;p&gt;As always, all code is available in &lt;a href="https://github.com/alexromanov/client-grpc-sample"&gt;github-repo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>automation</category>
      <category>testing</category>
      <category>grpc</category>
      <category>scala</category>
    </item>
    <item>
      <title>My biggest testing regrets</title>
      <dc:creator>Oleksandr Romanov</dc:creator>
      <pubDate>Sat, 12 Jun 2021 10:58:13 +0000</pubDate>
      <link>https://dev.to/al8xr/my-biggest-testing-regrets-2mhd</link>
      <guid>https://dev.to/al8xr/my-biggest-testing-regrets-2mhd</guid>
      <description>&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@brett_jordan?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Brett Jordan&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/regret?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing regrets
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://club.ministryoftesting.com/t/bloggers-club-june-2021-your-one-biggest-testing-regret/50695"&gt;Ministry of Testing Bloggers Club&lt;/a&gt; offered an exciting topic for June - "Your biggest testing regret."  &lt;/p&gt;

&lt;p&gt;I started my professional career in September 2011. My first job was as a QC Engineer, but I soon switched to test automation and software development. As of 2021, I worked in different companies - from banking and finance to gaming with various technology stacks.  &lt;/p&gt;

&lt;p&gt;I am not a fan of regrets. So in this blog post, I want to tell more about lessons learned than just simple regrets.   &lt;/p&gt;

&lt;h2&gt;
  
  
  Personal development inside the company
&lt;/h2&gt;

&lt;p&gt;During my first years in university and my first years in a full-time job, I hoped that somebody would "magically" create a strict development path for me.  &lt;/p&gt;

&lt;p&gt;"Just learn this and that, practice this, and you will become a middle/senior/lead test/automation engineer."   &lt;/p&gt;

&lt;p&gt;Unfortunately, it did not happen in university, so I needed to learn a lot by myself. So it did not occur at work.&lt;/p&gt;

&lt;p&gt;What I learned is that the only person responsible for your personal development - is you.&lt;br&gt;&lt;br&gt;
It is not your lead, manager, CTO, or career advisor. &lt;strong&gt;It is YOU&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt; need to think about what you want from your current and future career: whether it will be testing, development, automation, leading people, or starting your own company. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt; need to think about which companies do you want to work with in the future.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt; need to create a personal development plan for yourself. Analyze which skills do you need to have. Which frameworks or programming languages do you need to master. &lt;/p&gt;

&lt;p&gt;Think about it as an RPG game. &lt;/p&gt;

&lt;p&gt;Create a mind map with skills that you have, and want to have. It can be a path for the upcoming 3-6 months or a couple of years. &lt;/p&gt;

&lt;p&gt;Set goals and start to learn new things. Learn from books, courses, videos, blogs. Learn for colleagues. &lt;/p&gt;

&lt;p&gt;You can discuss your plan with your manager. Ask him/her whether you can apply new skills in your current project. Ask about future opportunities within a company. If you see that a company can't (or don't want) to support you in your development - consider changing your job. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Take responsibility for your own career "story," and you won't regret it.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Test engineering is considered as non-technical
&lt;/h2&gt;

&lt;p&gt;In many work environments where I worked, testers or automation engineers are considered "not-so-technical" engineers. It is a huge regret for the whole industry. &lt;/p&gt;

&lt;p&gt;Testers are just clicking buttons and file bugs. Testers just sent a message "Something is not working" without attaching any logs, environment information. Testers do not provide clear steps to reproduce the issues. Testers can't even give initial thoughts on the root cause of the bugs. &lt;/p&gt;

&lt;p&gt;I also thought in such a way for some time.&lt;/p&gt;

&lt;p&gt;The root cause of such a problem is because most QA courses do not provide a solid technical background on how systems work. The primary purpose of such classes is to teach you how to follow predefined test cases and file bugs. The most "technical" thing is firing a few HTTP calls manually or writing simple WebDriver tests for the Login page. &lt;br&gt;
And after all, what the heck do you want to learn from scratch after 1-2 month courses?&lt;/p&gt;

&lt;p&gt;As a result, most testers want to move to the development roles as soon as possible. It can be software development, managing positions, business analysts, etc. &lt;/p&gt;

&lt;p&gt;If you stay in testing for more than ten years, you feel like a "stranger" person. &lt;/p&gt;

&lt;p&gt;All of this is why testers themselves do not know or feel that their work can be technical.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But magic can happen.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;If you invest in developing your technical skills, you, as a tester, can see that the overall picture is changing.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It changes&lt;/strong&gt; when you go to the developer with an initial investigation of the root cause. Or with possible solutions along with the trade-offs.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It changes&lt;/strong&gt; when you describe a possible "what if" scenario during a discussion of future deployment strategies.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It changes&lt;/strong&gt; when you highlight possible issues with scalability or reliability when you talk with architects.  &lt;/p&gt;

&lt;p&gt;And after all, &lt;strong&gt;it changes&lt;/strong&gt; when you clearly show the risks to managers and stakeholders, supplying it with business metrics and data - not just words.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Developing technical skills is challenging. It requires time and dedication. But it pays off.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Testers are engineers. They can perform academic researches. They can apply programming to create the tools which benefit the team. They can do a complex analysis of the system to find "weak points." &lt;/p&gt;

&lt;p&gt;That's what engineers can and should do. &lt;/p&gt;

</description>
      <category>testing</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Paper review: Simple Testing in Distributed Systems</title>
      <dc:creator>Oleksandr Romanov</dc:creator>
      <pubDate>Tue, 01 Jun 2021 05:05:57 +0000</pubDate>
      <link>https://dev.to/al8xr/paper-review-simple-testing-in-distributed-systems-gf2</link>
      <guid>https://dev.to/al8xr/paper-review-simple-testing-in-distributed-systems-gf2</guid>
      <description>&lt;h2&gt;
  
  
  New format
&lt;/h2&gt;

&lt;p&gt;I enjoy reading research papers. Here you can get an overview of the latest concepts and ideas in the field. You can get an overview of the newest tool and approaches from the top companies.  &lt;/p&gt;

&lt;p&gt;You can also get the results of the academic research performed by scientists on a big chunk of data. Reading a research paper is like reading a book, but in a much smaller format and with a lot of new information per page.  &lt;/p&gt;

&lt;p&gt;Recently, I started to look for and read research papers about testing in the various types of distributed systems. &lt;/p&gt;

&lt;p&gt;That's why I want to start a series of posts with a common title: "Paper Review". Here I will share the most exciting papers about quality that I found. &lt;/p&gt;

&lt;h2&gt;
  
  
  Distributed systems
&lt;/h2&gt;

&lt;p&gt;What is a "distributed system"? In its simplest definition, it is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;group of computers&lt;/strong&gt; that&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;work together on a given task&lt;/strong&gt; and&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;communicate with each other by passing messages&lt;/strong&gt; and&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;appear to a user as a single machine&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It turns out that distributed systems are everywhere. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Internet&lt;/strong&gt; is in some way a distributed system of computers that provide information to the user. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Web / Application monolithic backend&lt;/strong&gt; is a distributed system in a case when deployed onto multiple servers. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backend based on microservices&lt;/strong&gt; is also distributed system. Dozens and hundreds of microservices are working together to provide some results. And each microservice also can have multiple copies. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Blockchains&lt;/strong&gt; are distributed systems. Underneath it is a system of many computers sending each other information about a newly added block of transactions. &lt;/p&gt;

&lt;p&gt;Almost any modern application contains parts distributed in nature: storages, message queues, load balancers, etc. &lt;/p&gt;

&lt;h2&gt;
  
  
  Testing in distributed systems
&lt;/h2&gt;

&lt;p&gt;If you are working in IT, you know that testing can be challenging and complex. The main complexity is that the number of test cases and the number of potential issues in the system are almost infinite. &lt;/p&gt;

&lt;p&gt;It even gets more challenging when the system is distributed. &lt;br&gt;
You need to check application functionality.&lt;br&gt;&lt;br&gt;
But you also need to check how data is replicated between different nodes in the storage system.  &lt;/p&gt;

&lt;p&gt;You need to test any synchronization issues between nodes located in different timezones (e.g., providing user data from other CDNs).  &lt;/p&gt;

&lt;p&gt;And the main thing - you need to test how the system will behave when one or more nodes are down (restarting or broken).  &lt;/p&gt;

&lt;p&gt;It is complicated for a couple of nodes, but what can we do if the number of nodes is 100s or 1000s? &lt;/p&gt;

&lt;h2&gt;
  
  
  An overview
&lt;/h2&gt;

&lt;p&gt;The paper &lt;a href="https://www.usenix.org/system/files/conference/osdi14/osdi14-paper-yuan.pdf"&gt;"Simple Testing Can Prevent Most Critical Failures"&lt;/a&gt; by Ding Yuan et al. gives a good view of which failures can happen in &lt;strong&gt;real-world production systems&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;The authors performed an analysis of critical failures of the five distributed systems: &lt;a href="https://cassandra.apache.org/"&gt;Cassandra&lt;/a&gt;, &lt;a href="https://hbase.apache.org/"&gt;HBase&lt;/a&gt;, &lt;a href="https://hadoop.apache.org/docs/r1.2.1/hdfs_design.html"&gt;HDFS&lt;/a&gt;, &lt;a href="https://hadoop.apache.org/docs/r1.2.1/mapred_tutorial.html"&gt;MapReduce&lt;/a&gt;, and &lt;a href="https://redis.io/"&gt;Redis&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2IptZBK5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/huqv2ztf98bcw2jh91d1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2IptZBK5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/huqv2ztf98bcw2jh91d1.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;During an investigation, they reveal a lot of interesting findings. Here are the most interesting ones:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The majority of the failures require more than one input event, but it requires no more than three events in most cases. 50% of the losses require only two nodes.  &lt;/p&gt;

&lt;p&gt;This finding says that you don't need to simulate a large production cluster with thousands of nodes for reproducing the failure or for testing. You need only two or three nodes. It simplifies the approach to building test environments. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KXV0-Hxv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hyakojyrjuqul1jtq5m8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KXV0-Hxv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hyakojyrjuqul1jtq5m8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The majority (74%) of the failures are deterministic. It means that it is possible to get the correct order of multiple events to simulate the failure. Random-based test generation can help, but an order of events is defined and can be transformed into a test case in most cases. &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XA3vPfaa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ysb5fmgr8urijisat7dj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XA3vPfaa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ysb5fmgr8urijisat7dj.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;76% of failures print log error messages and have logged inputs. So they can be clearly understood and reproduced.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The unit test can reproduce 77% of the production failures! Do not underestimate the power of unit testing. Integration and end-to-end testing can reveal these problems - but they didn't find them as these bugs slipped to production.&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EZ8ksGbp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cgqvzu3lsxp7jem138jp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EZ8ksGbp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cgqvzu3lsxp7jem138jp.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;92% of the failures are due to incorrect error handling (fatal and non-fatal). A lot of error handlers were too general or missed some extra corner cases. In some cases, it even contains TODO and FIXME comments. It means that error handling code should be analyzed by external tools and other developers and testers to find potential gaps.&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NgOD2dM8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pw0rud387fykmhs261io.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NgOD2dM8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pw0rud387fykmhs261io.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As you see, distributed systems add additional complexity to testing due to their scale. But it turns out that the most trivial testing approaches like unit testing of error-handling cases - can prevent the majority of such issues.  &lt;/p&gt;

&lt;p&gt;We, as quality engineers, should help developers to identify such potential gaps in coverage. It can be by a manual investigation; it can be by improving existing code coverage scanners. &lt;/p&gt;

&lt;p&gt;What was your most exciting bug found in a distributed environment? &lt;/p&gt;

</description>
      <category>distributedsystems</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
