<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.3">Jekyll</generator><link href="https://alexromanov.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://alexromanov.github.io/" rel="alternate" type="text/html" /><updated>2023-03-26T10:02:36+00:00</updated><id>https://alexromanov.github.io/feed.xml</id><title type="html">Test Engineering Notes</title><subtitle>Notes and experiences in test engineering, automation and distributed systems</subtitle><entry><title type="html">On choosing and changing languages for test automation</title><link href="https://alexromanov.github.io/2022/10/30/choose-your-language/" rel="alternate" type="text/html" title="On choosing and changing languages for test automation" /><published>2022-10-30T06:00:00+00:00</published><updated>2022-10-30T06:00:00+00:00</updated><id>https://alexromanov.github.io/2022/10/30/choose-your-language</id><content type="html" xml:base="https://alexromanov.github.io/2022/10/30/choose-your-language/">&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/photos/C7B-ExXpOIE?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditShareLink&quot;&gt;Javier Allegue Barros on Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You are at the beginning of your testing career…&lt;/strong&gt; You see that in many job descriptions, they ask about test automation skills. Or you heard that by working in automation, you can earn more money (which depends). 
&lt;strong&gt;Which programming language to choose? Which language and tech stack is best of the best? Is there a single choice for it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It can happen to anybody. You can be frustrated in your current job. You can feel that you are doing the simple things, and your progression is stopped. You also desire more salary or more significant responsibilities. 
So the call or message notification on Linkedin about a &lt;strong&gt;new and fancy job opportunity is coming&lt;/strong&gt; just in time. &lt;strong&gt;But the issue here is that this new job is in a completely different tech stack or programming language. What can you do with it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Today I want to share my thoughts on choosing the first programming language. Also - we will think together whether it is worth changing between language and tech stack - and how to make the such process beneficial for you and your manager.&lt;/p&gt;

&lt;h1 id=&quot;my-story&quot;&gt;My story&lt;/h1&gt;
&lt;p&gt;I had various jobs and titles in my 10+ years of IT industry journey. I was a Test Automation Specialist, a QA &amp;amp; Testing Analyst, an SDET, a QA Automation Engineer, and even a Software Engineer.&lt;/p&gt;

&lt;p&gt;In fact, &lt;strong&gt;it is not about how fancy is your position’s name.&lt;/strong&gt; &lt;strong&gt;It is all about your responsibilities and your influence on the team&lt;/strong&gt; or department level.&lt;/p&gt;

&lt;p&gt;Over the years, I’ve changed automation languages ​​several times:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;at my first job, I wrote UI autotests in C# + Specflow;&lt;/li&gt;
  &lt;li&gt;then - wrote API tests on Groovy DSL (SoapUI) and simply on “pure” Java;&lt;/li&gt;
  &lt;li&gt;then it was the Ui web test automation with C# again;&lt;/li&gt;
  &lt;li&gt;then it was a big project, and tests on Scala.&lt;/li&gt;
  &lt;li&gt;Then it was Java, Spring Boot and software engineering job.&lt;/li&gt;
  &lt;li&gt;Right now, I am writing my tests and tools mainly in Scala.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;questions-to-consider-before-choosing-a-language&quot;&gt;Questions to consider before choosing a language&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;/img/20221030/skill.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Image from &lt;a href=&quot;https://www.reddit.com/r/ProgrammerHumor/comments/v1lx1u/this_is_a_meme/&quot;&gt;Reddit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before choosing the programming language for automation, you need to ask yourself a set of questions.&lt;/p&gt;

&lt;h2 id=&quot;project-related&quot;&gt;Project-related:&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;Technological stack and architecture.&lt;/li&gt;
  &lt;li&gt;Testing processes. Are there testing processes on the project? How do you plan to use automation testing? Who will be responsible for such tests - testers, developers, or a separate team of engineers?&lt;/li&gt;
  &lt;li&gt;Test automation strategy. Is there an ultimate goal of automation? What types of automation tests do you plan to write? When will such tests be executed? How do you use the test reports?&lt;/li&gt;
  &lt;li&gt;Programming and automation experience. Do you have programming experience? Did you write automation tests at all?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;language-related&quot;&gt;Language-related:&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;How many vacancies are currently on the market for this language&lt;/li&gt;
  &lt;li&gt;How deeply do you plan to learn this language? What is your technical background?&lt;/li&gt;
  &lt;li&gt;Is the language and the infrastructure around it mature enough? Do stable frameworks and tools exist that will allow you to quickly write the necessary solutions?&lt;/li&gt;
  &lt;li&gt;How do you plan to improve your career by learning a language?&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;on-environment&quot;&gt;On environment&lt;/h1&gt;

&lt;p&gt;Your work environment matters. Depending on the team, its skills, and you personally - the choices for language can be different. Let me show you a few cases and possible solutions for dealing with automation.&lt;/p&gt;

&lt;h2 id=&quot;one-tester-a-small-team-no-prior-automation-experience&quot;&gt;One tester. A small team. No prior automation experience.&lt;/h2&gt;

&lt;p&gt;Options:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Invite a short-term automation consultant. They will help develop an automation strategy and initial Proof-of-Concept for automation tests.&lt;/li&gt;
  &lt;li&gt;Choose the same programming language for automation that the developers in your team use. They will be able to advise and help you with the tests. The downside of this approach is that developers can write complex programming languages ​​that are not very efficient for writing simple end-to-end tests. (Or course, you also can write Selenium tests in Haskell.)&lt;/li&gt;
  &lt;li&gt;Find a mentor (inside your company or elsewhere) to help and guide you in learning automation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;one-tester-a-small-team-some-automation-experience&quot;&gt;One tester. A small team. Some automation experience.&lt;/h2&gt;

&lt;p&gt;Options:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Choose the language you know best. Also, consider how many automation tools and libraries exist for the language. It may happen that many tools will have to be written: “from scratch.”&lt;/li&gt;
  &lt;li&gt;Alternatively, you can choose the language and stack identical to what the developers use. Learning a new programming language to create several UI autotests is relatively easy (if you already have some background).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;a-team-of-testers-no-automation-experience-youre-the-lead&quot;&gt;A team of testers. No automation experience. You’re the lead.&lt;/h2&gt;

&lt;p&gt;Options:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Select an individual tester from the team and train him or her in test automation.&lt;/li&gt;
  &lt;li&gt;Hire a dedicated automation engineer who will later train all testers in automation.&lt;/li&gt;
  &lt;li&gt;Train developers to implement automation tests by themselves. (Difficulty level: HARD).&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;on-choosing-languages&quot;&gt;On choosing languages&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;/img/20221030/language.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Image from &lt;a href=&quot;https://www.reddit.com/r/ProgrammerHumor/comments/7x96ts/learning_a_new_programming_language/&quot;&gt;Reddit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are many programming languages. Some languages are harder to learn. But such languages can give a boost to writing tools.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;If you like the world of front-end - then your choice is &lt;strong&gt;Javascript or Typescript&lt;/strong&gt; and its army of frameworks. This world of tools and libraries is a very dynamic one. You will always have a job!&lt;/li&gt;
  &lt;li&gt;If you’re more into network stuff, hacking, data science, or other back-end stuff (or just like simple and friendly code) - look towards &lt;strong&gt;Python&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;For those who want enterprise-level stability, consider &lt;strong&gt;Java&lt;/strong&gt; or &lt;strong&gt;C#&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Those who want to work with blockchain - can learn smart-contract languages like &lt;strong&gt;Solidity&lt;/strong&gt;, &lt;strong&gt;Plutus&lt;/strong&gt;, and other platform-specific ones. You need to learn &lt;strong&gt;Haskell&lt;/strong&gt;, &lt;strong&gt;Rust&lt;/strong&gt;, and &lt;strong&gt;C++&lt;/strong&gt; for more low-level things in the blockchain world.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;about-new-languages&quot;&gt;About new languages&lt;/h2&gt;

&lt;p&gt;If you choose a programming language that is new or not a mainstream, then be prepared to learn it deeply and then look for a job for a longer time. As a side effect, the salaries may be slightly higher. But it may NOT be.&lt;/p&gt;

&lt;p&gt;Additionally, if the language is new, you will need to write a lot of the functionality of the frameworks of other languages ​​by yourself. On the one hand, it’s an opportunity to improve your technical skills. On the other hand, it requires time and effort (which may not be available to you).&lt;/p&gt;

&lt;h1 id=&quot;on-changing-languages-and-tech-stacks&quot;&gt;On changing languages and tech stacks&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;/img/20221030/change.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Image from &lt;a href=&quot;https://www.reddit.com/r/ProgrammerHumor/comments/8vrugj/programming_languages_problems_and_html/&quot;&gt;Reddit&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;If you are a Junior or Middle automation engineer.&lt;/strong&gt; It is relatively simple to change the programming language and stacks at this level. If the new project has an established framework and/or senior engineer to mentor you - you can switch without fear. You will need to learn a lot - but a good mentor can make this learning process as quick and painless as possible.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;If you are a Senior engineer.&lt;/strong&gt; If you join the new company as the first engineer in the team, you will need time to learn new things and write proofs-of-concept that might only work on the first try. On the other hand - if you join a well-established team, your onboarding process will be more straightforward.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Switching between statically typed languages&lt;/strong&gt; ​​(Java, C#, and C-like languages ​​in general) is quite simple. It will be a little more challenging to transition from statically typed to dynamically typed languages, such as JS, Python, Groovy, Ruby, etc. (or vice versa). Plan more time for learning new concepts.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Few words about functional programming languages&lt;/strong&gt; ​​(Scala, Closure, Haskell, and others). It is possible to write in OOP style on some of them (in particular on Scala). For tests, in principle, it will be enough. But functional programming will still need to be mastered to get the most out of the language. And it takes even more time than the languages ​​from the previous point. Plus, you can only write in a functional style in languages like Haskell or Closure.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;About working at FAANG and other western startups.&lt;/strong&gt; They all hire engineers - the people who can master one or another language in a short period (not instantly, of course) and write production or test code with it. But do not worry. In most cases, such companies will have a lot of experienced engineers who will help with code reviews and feedback. So what matters here - is your basic technical knowledge and problem-solving experience. Programming language - is only one thing among your tools.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;on-skills&quot;&gt;On skills&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Programming language is only a tiny part of what a test engineer or SDET should be able to do in automated testing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In addition to the language, there are also basic approaches to testing and automation. There is technical knowledge of various systems’ architecture and how to test them.&lt;/p&gt;

&lt;p&gt;There are many additional tools for writing and running tests - build tools, automation frameworks, various libraries for logging, parallel runs, reporting, and CICD tools. And also - design patterns and the ability to write clean and understandable code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Most of the automation skills do not depend on the programming language.&lt;/strong&gt; You can find analogs in the selected technology stack for most of the tools. If such tools do not exist in the chosen technology, why not build it yourself?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The main job of an engineer is to solve a business problem most efficiently. Effectiveness here lies primarily in how fast, scalable, and understandable the tool or approach is to other engineers and managers.&lt;/strong&gt;&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;/img/20221030/automation.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Image from &lt;a href=&quot;https://www.reddit.com/r/ProgrammerHumor/comments/gvvq3t/if_u_didnt_spend_6_hours_automating_a_task_that/&quot;&gt;Reddit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choosing a programming language for automation - is a hard thing. Especially if you are a single tester in a small team. Each language has its pros and cons. Each language brings an ecosystem with it. But &lt;strong&gt;asking good questions BEFORE making such a choice&lt;/strong&gt; - &lt;strong&gt;can decrease the amount of “headache”&lt;/strong&gt; in the future.&lt;/p&gt;

&lt;p&gt;Changing languages and stacks later in your career also have their own implications. You can be a &lt;strong&gt;generalist&lt;/strong&gt; and scratch the surface of many languages. Or you can be a &lt;strong&gt;specialist&lt;/strong&gt; in one language - but do technically complex things and optimizations. &lt;strong&gt;It’s up to you to decide which engineer you wanna be.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the end, I want to state a few general things that you should never forget when you work with test automation:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;A few stable and fast tests are better than a “super framework.”&lt;/strong&gt; If you plan to create only a Smoke suite from a pair of end-to-end tests “for every day, “ you can do it with almost any tool. Just make sure that the tests are fast and stable. Such tests will bring benefits to the whole team.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Automation can take many forms.&lt;/strong&gt; It can be a UI or API test for the most critical features, deployment scripts, or database migration. Small script that automate daily routine tasks can bring more value to the team than a lot of simple UI tests.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Automation strategy is the first step.&lt;/strong&gt; If you plan to create automation tests at different levels, think about test coverage, launch on various platforms, then first create and communicate the automation strategy to management. Without a clear understanding of the “end” point, you will not be able to tell whether you are moving in the right direction.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Learn programming and the technology stack.&lt;/strong&gt; Writing a large project for automation requires the same knowledge and programming skills as writing feature code. Therefore, constantly improve your level of expertise.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;</content><author><name>Oleksandr Romanov</name></author><summary type="html">Photo by Javier Allegue Barros on Unsplash</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://alexromanov.github.io/img/20221030/choice.jpg" /><media:content medium="image" url="https://alexromanov.github.io/img/20221030/choice.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">On test engineer’s maturity</title><link href="https://alexromanov.github.io/2022/09/25/test-engineer-maturity-questions/" rel="alternate" type="text/html" title="On test engineer’s maturity" /><published>2022-09-25T06:00:00+00:00</published><updated>2022-09-25T06:00:00+00:00</updated><id>https://alexromanov.github.io/2022/09/25/test-engineer-maturity-questions</id><content type="html" xml:base="https://alexromanov.github.io/2022/09/25/test-engineer-maturity-questions/">&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/photos/9lcTOjGQRsI?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditShareLink&quot;&gt;Lance Grandahl on Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;questions&quot;&gt;Questions&lt;/h1&gt;
&lt;p&gt;From time to time, similar questions arise in various tester chats and forums:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Do I know enough as a junior or trainee?&lt;/li&gt;
  &lt;li&gt;What should the middle engineer know?&lt;/li&gt;
  &lt;li&gt;When to understand that you are a senior?&lt;/li&gt;
  &lt;li&gt;How to get the position of lead or manager?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have also asked myself and other people such questions. But unfortunately, he did not receive comprehensive answers.&lt;br /&gt;
After all, there is no single correct answer to such questions. Everything depends on the context: you, the company, and the market.&lt;/p&gt;

&lt;h1 id=&quot;test-engineer-maturity&quot;&gt;Test Engineer Maturity&lt;/h1&gt;

&lt;p&gt;Instead of looking for complex answers, I suggest paying attention to what questions we ask ourselves at each stage of our career development.
Each company has its own stages of career development, but I see the following: Junior =&amp;gt; Middle =&amp;gt; Senior =&amp;gt; Lead =&amp;gt; Manager =&amp;gt; Consultant =&amp;gt; “Guru”.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220925/maturity.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;junior&quot;&gt;Junior&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;How to test this feature or application?&lt;/li&gt;
  &lt;li&gt;Which test design technique is best?&lt;/li&gt;
  &lt;li&gt;What is Git, and why is it needed?&lt;/li&gt;
  &lt;li&gt;Which programming language to choose for automation (to get bigger salary)?&lt;/li&gt;
  &lt;li&gt;What is the best testing tool?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;middle&quot;&gt;Middle&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;How to properly configure CICD pipeline?&lt;/li&gt;
  &lt;li&gt;How to fix all flaky tests?&lt;/li&gt;
  &lt;li&gt;What are design patterns, and how to apply them?&lt;/li&gt;
  &lt;li&gt;Why do we need to write clean code and follow coding conventions?&lt;/li&gt;
  &lt;li&gt;How to run tests in multiple threads somewhere on Selenoid?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;senior&quot;&gt;Senior&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;How to improve the testability of a particular feature or service?&lt;/li&gt;
  &lt;li&gt;What are the problems with the system architecture? What will happen if “this individual component” on the diagram stops working correctly?&lt;/li&gt;
  &lt;li&gt;How much business value do self-tests bring?&lt;/li&gt;
  &lt;li&gt;How to encourage the entire team, from developers to managers, to use test results?&lt;/li&gt;
  &lt;li&gt;Which tests are better to do ‘manually’ rather than to spend time on automation?&lt;/li&gt;
  &lt;li&gt;How quickly and safely does this or that component work? But how does one component’s bad performance affect the system’s performance as a whole?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;lead&quot;&gt;Lead&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;How to properly organize testing processes in a team?&lt;/li&gt;
  &lt;li&gt;How to ensure that the team achieves business goals?&lt;/li&gt;
  &lt;li&gt;How to create a culture of shared responsibility for quality in the team?&lt;/li&gt;
  &lt;li&gt;How to collect metrics, work with priorities, and communicate with different teams?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;manager&quot;&gt;Manager&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;How does testing help minimize business risks?&lt;/li&gt;
  &lt;li&gt;How to motivate test engineers to grow and develop?&lt;/li&gt;
  &lt;li&gt;How to create testing vision for the company?&lt;/li&gt;
  &lt;li&gt;How to set up processes and engineering culture at the company level?&lt;/li&gt;
  &lt;li&gt;How to communicate test results to senior management (in their language)?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;consultant&quot;&gt;Consultant&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;How to create a better testing strategy for a specific company in a particular context?&lt;/li&gt;
  &lt;li&gt;How to convince the client that this tool or approach is better?&lt;/li&gt;
  &lt;li&gt;How to quickly make a Proof-of-Concept of an automation solution and get feedback?&lt;/li&gt;
  &lt;li&gt;How do you train engineers or managers on a chosen concept, approach, or tool?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;guru&quot;&gt;“Guru”&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;Why do we test?&lt;/li&gt;
  &lt;li&gt;How does testing differ from verification?&lt;/li&gt;
  &lt;li&gt;How can we tell if our expected results are correct?&lt;/li&gt;
  &lt;li&gt;How do we know what we know?&lt;/li&gt;
  &lt;li&gt;How do we learn?&lt;/li&gt;
  &lt;li&gt;Are there universal approaches and heuristics for testing?&lt;/li&gt;
  &lt;li&gt;How to measure or change people’s perception of quality?&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h1&gt;
&lt;p&gt;Of course, if you are at the same stage, no one forbids you to ask any other questions from different levels.&lt;/p&gt;

&lt;p&gt;But the effectiveness of your work and the answers to questions will directly depend on your skill level and the scope of work.&lt;/p&gt;

&lt;h2 id=&quot;and-what-questions-do-you-ask-yourself-on-the-project&quot;&gt;And what questions do YOU ask yourself on the project?&lt;/h2&gt;</content><author><name>Oleksandr Romanov</name></author><summary type="html">Photo by Lance Grandahl on Unsplash</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://alexromanov.github.io/img/20220925/ladder.jpg" /><media:content medium="image" url="https://alexromanov.github.io/img/20220925/ladder.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Testability and how to improve it</title><link href="https://alexromanov.github.io/2022/08/14/what-is-testability/" rel="alternate" type="text/html" title="Testability and how to improve it" /><published>2022-08-14T06:00:00+00:00</published><updated>2022-08-14T06:00:00+00:00</updated><id>https://alexromanov.github.io/2022/08/14/what-is-testability</id><content type="html" xml:base="https://alexromanov.github.io/2022/08/14/what-is-testability/">&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/photos/-Cm7hnp4WOg?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditShareLink&quot;&gt;Jeswin Thomas on Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;why-is-it-testability&quot;&gt;Why is it testability?&lt;/h2&gt;
&lt;p&gt;At first glance, the typical test engineer already has enough things to do:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Work out the requirements.&lt;/li&gt;
  &lt;li&gt;Create plans and strategies.&lt;/li&gt;
  &lt;li&gt;Write test cases.&lt;/li&gt;
  &lt;li&gt;Report and re-check bugs.&lt;/li&gt;
  &lt;li&gt;TEST!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Somewhere between these things, you still have to find time for automation. And you still need to make a demo for the customer.&lt;/p&gt;

&lt;p&gt;Why even bother with that &lt;strong&gt;testability&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;Isn’t that the task of whoever writes this code? Is it possible for a test engineer to influence the team (especially the architects and developers) - and make the software a little more open and easy for testing?&lt;/p&gt;

&lt;p&gt;Let’s try to figure this out a little together.&lt;/p&gt;

&lt;h2 id=&quot;testability-officially-and-not-so-much&quot;&gt;Testability: officially and not so much&lt;/h2&gt;
&lt;p&gt;What is the definition of testability given by industry standards?&lt;/p&gt;

&lt;p&gt;According to &lt;a href=&quot;https://www.iso.org/obp/ui/#iso:std:iso-iec:25010:ed-1:v1:en&quot;&gt;ISO/IEC 25010:2011&lt;/a&gt;:
&lt;em&gt;Testability - degree of effectiveness and efficiency with which test criteria can be established for a system, product, or component, and tests can be performed to determine whether those criteria have been met.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;According to &lt;a href=&quot;https://glossary.istqb.org/en/term/testability-3&quot;&gt;ISTQB terminology&lt;/a&gt;:
&lt;em&gt;Testability - The capability of the software product to enable modified software to be tested.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In simple terms, &lt;strong&gt;testability is how convenient and easy it is to test an individual component and the entire system.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testability&lt;/strong&gt; depends on multiple factors:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;How easy is it to control the internal state of the components during testing?&lt;/li&gt;
  &lt;li&gt;Is it hard to observe the system and its components during tests?&lt;/li&gt;
  &lt;li&gt;Is it possible to test components in isolation?&lt;/li&gt;
  &lt;li&gt;How fully documented is the component?&lt;/li&gt;
  &lt;li&gt;Is it doable to write automated tests for it?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;testability-at-the-code-level&quot;&gt;Testability at the code level&lt;/h2&gt;
&lt;p&gt;To efficiently test classes at the module level, you need to be able to create Mock objects for all class dependencies.&lt;/p&gt;

&lt;p&gt;If the developer applies the &lt;a href=&quot;https://en.wikipedia.org/wiki/Dependency_inversion_principle&quot;&gt;&lt;strong&gt;Dependency Inversion&lt;/strong&gt;&lt;/a&gt; principle, there will be significantly fewer testing problems. Ideally, you need to pass all dependencies through the class constructor.&lt;/p&gt;

&lt;p&gt;Also, don’t forget about &lt;a href=&quot;https://en.wikipedia.org/wiki/Observability&quot;&gt;&lt;strong&gt;observability&lt;/strong&gt;&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Controllability&quot;&gt;&lt;strong&gt;controllability&lt;/strong&gt;&lt;/a&gt;, even at the class level. The developer (or test engineer) must be able to see the state of critical parts of the object at any time. It would be much better to add different methods to get this information directly to the test class.&lt;/p&gt;

&lt;p&gt;But still - this aspect is entirely under the responsibility of the developer.&lt;/p&gt;

&lt;h2 id=&quot;testability-at-the-architecture-level&quot;&gt;Testability at the architecture level&lt;/h2&gt;
&lt;p&gt;A practical tip at the architecture level would be to separate &lt;strong&gt;infrastructure&lt;/strong&gt; and &lt;strong&gt;domain&lt;/strong&gt; code. By domain code, we understand all the code responsible for business logic. Infrastructure code works with external dependencies - databases, message queues, third-party services, etc.&lt;/p&gt;

&lt;p&gt;To separate one type of code from another, you can design components using the &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Hexagonal_architecture_(software)&quot;&gt;Ports and Adapters (Hexagonal)&lt;/a&gt;&lt;/strong&gt; pattern. &lt;strong&gt;Alistair Cockburn&lt;/strong&gt; proposed this model in 2005.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220814/portadapters.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Maurício Aniche gives a more practical example of such a model in the book &lt;strong&gt;&lt;a href=&quot;https://www.manning.com/books/effective-software-testing&quot;&gt;Effective Software Testing&lt;/a&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220814/portsexplained.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;testability-through-the-eyes-of-testers&quot;&gt;Testability through the eyes of testers&lt;/h2&gt;
&lt;p&gt;Okay, but how can a particular test engineer affect testability?&lt;/p&gt;

&lt;h3 id=&quot;unique-properties-of-elements&quot;&gt;Unique properties of elements&lt;/h3&gt;
&lt;p&gt;If you’ve written more than one UI test, you can tell a lot about the pain of “long and fragile” locators. Changing the elements on the page is one of the main reasons for the instability of such tests.&lt;/p&gt;

&lt;p&gt;As a test engineer, you can do two things in this case to improve testability:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Agree with the team (or architects) to add unique properties for each new critical element;&lt;/li&gt;
  &lt;li&gt;Agree with the developers that you will add unique properties to elements whenever it’s needed (for legacy components);&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Having an special property like &lt;strong&gt;“automation-id”&lt;/strong&gt; or &lt;strong&gt;“data-id”&lt;/strong&gt; for a web element - &lt;strong&gt;saves a time and nerves&lt;/strong&gt; for a test engineer.&lt;/p&gt;

&lt;h3 id=&quot;components-in-isolation&quot;&gt;Components in isolation&lt;/h3&gt;
&lt;p&gt;Please keep track of how convenient it is to test the component in isolation. Ideally, a developer or tester should isolate a single part (e.g., a single microservice) and test only the business logic.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Is it easy to replace the actual database with an in-memory one?&lt;/li&gt;
  &lt;li&gt;Is it convenient to fill the database with the necessary test data for the correct component operation?&lt;/li&gt;
  &lt;li&gt;Is it easy to block external requests to third-party services?&lt;/li&gt;
  &lt;li&gt;Is it hard to send or read messages in the Message Queue for a single service?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can always work together with a developer to build such tools for the components of your system. In many cases these tools can be find as libraries. If not - it is a good point to create it and spread as inner source in the organization.&lt;/p&gt;

&lt;h3 id=&quot;api-for-system-management&quot;&gt;API for system management&lt;/h3&gt;
&lt;p&gt;It is good to analyze how you test (from time to time). Some components in the system may work using probabilities or specific third-party data. The tests for such components will be unstable. But such systems should be tested and, ideally - automated as well.&lt;/p&gt;

&lt;p&gt;In search of the answers, we can think of it as a system of saves in a computer game. 
Imagine that you need to test how the “boss” behavior at the end of the level. You can verify it by playing the whole level from the start till the end. If we talk about one or two minutes - it is ok. But if each level in the game takes even ten minutes or more - such tests quickly become unrealistically long.&lt;/p&gt;

&lt;p&gt;A better way will be to use magic save, reach the end of the level and test exact behavior.&lt;/p&gt;

&lt;p&gt;The solution is to &lt;strong&gt;make a separate test API that will allow you to bring the system to one or another state.&lt;/strong&gt; Using such API will make tests faster and increase the stability and predictability of the system under test (at a certain level).&lt;/p&gt;

&lt;p&gt;That is the reason why many games have a long list of cheat codes.&lt;/p&gt;

&lt;p&gt;You can think about such a “cheat” system in the context of your application. These can be special commands you need to enter or separate ways of creating data that the system will process as a test (even in production). Such data will then be easier to filter and analyze.&lt;/p&gt;

&lt;h2 id=&quot;and-how-do-you-improve-testability-on-your-project&quot;&gt;And how do YOU improve testability on your project?&lt;/h2&gt;</content><author><name>Oleksandr Romanov</name></author><summary type="html">Photo by Jeswin Thomas on Unsplash</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://alexromanov.github.io/img/20220814/testability.jpg" /><media:content medium="image" url="https://alexromanov.github.io/img/20220814/testability.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">The most complicated automated tests</title><link href="https://alexromanov.github.io/2022/07/17/most-complicated-tests/" rel="alternate" type="text/html" title="The most complicated automated tests" /><published>2022-07-17T06:00:00+00:00</published><updated>2022-07-17T06:00:00+00:00</updated><id>https://alexromanov.github.io/2022/07/17/most-complicated-tests</id><content type="html" xml:base="https://alexromanov.github.io/2022/07/17/most-complicated-tests/">&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/photos/Iq9SaJezkOE?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditShareLink&quot;&gt;GR Stocks on Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Are UI tests that easy to write and maintain? Are unit and integration tests really the most complicated tests.&lt;/p&gt;

&lt;p&gt;This blog post will explain my thoughts on which tests are complex and why. If you agree or disagree with these thoughts, let’s discuss them in the comments.&lt;/p&gt;

&lt;h2 id=&quot;what-started-it-all&quot;&gt;What started it all?&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/img/20210712/test-layers.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;At the start of my career in test automation, I focused entirely on &lt;strong&gt;UI tests&lt;/strong&gt;. Then, after some time, I got to know the zen of the &lt;strong&gt;API level&lt;/strong&gt; and started writing such tests wherever possible (wherever that API existed). It was a time of SOAP and REST HTTP testing.&lt;/p&gt;

&lt;p&gt;But during the first years, no matter how many automation tests I wrote, I always thought my tests were too easy. 
Real “hardcore” developers write complex and scary unit and integration tests. To write those unit tests, you must know the programming language and frameworks very profoundly.&lt;/p&gt;

&lt;p&gt;These thoughts were in my head until I decided to look at frameworks for unit testing and unit tests in one of the projects at work.&lt;/p&gt;

&lt;h2 id=&quot;unit-tests&quot;&gt;Unit tests&lt;/h2&gt;

&lt;p&gt;On the one hand, it seems that unit tests are difficult to write. But it becomes much easier after you understand the very essence of such tests and master at least the basic capabilities of any test framework (such as &lt;strong&gt;JUnit&lt;/strong&gt;), mainly when you write features and tests yourself.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220717/unit.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We concentrate on class level (or several closely related classes) in unit testing. The main idea is to test business logic here. Then you can mock all external calls using a mocking framework such as &lt;strong&gt;Mockito&lt;/strong&gt;. Simple test data is created in the form of stubs or fakes.&lt;/p&gt;

&lt;p&gt;When you figure out how to write mocks and tests correctly, the speed of creating new tests depends only on the complexity of the business logic of the class itself. As for supporting such tests, it is also not tricky: such tests are closely related to the feature code, so they need to be changed often.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implementation complexity of unit tests is easy as well as the maintenance cost.&lt;/strong&gt; The only question is how testable the feature code is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The critical thing about unit tests is that the developer fully controls the environment, test data, and behavior of dependencies.&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;integration-tests&quot;&gt;Integration tests&lt;/h2&gt;

&lt;p&gt;Integration testing is one of the most controversial themes among engineers. Every person can understand the integration level on their own.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220717/integration.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;By integration tests, I will understand the testing of individual components in isolation from the entire system. For example, when we have many microservices on the backend, the integration test can be both at the service level (we check the business logic of the service as a whole, and at a more granular level - we verify the operation of the service with the database).&lt;/p&gt;

&lt;p&gt;In this case, we mock requests to other services or third-party components using Wiremock. Other dependencies can be run locally as &lt;strong&gt;Docker&lt;/strong&gt; containers (&lt;strong&gt;testcontainers&lt;/strong&gt;) or in the form of in-memory databases.&lt;/p&gt;

&lt;p&gt;Such tests show a more realistic picture of the operation of part of the system and its components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The implementation complexity of such tests is average.&lt;/strong&gt; The main problem here is the correct configuration of dependencies for the service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The maintenance is also not very hard.&lt;/strong&gt; If you have a proper design for your test and feature code, the interfaces between components will be more stable than in unit tests. So the change of database or messaging broker should not have a high impact on the core logic of the system or service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;As for the control, the developer has limited control over the dependencies. It is possible to configure the database or message queue.&lt;/strong&gt; You can also set some test data as pre- or post-conditions. But you can’t be 100% sure that the DB implementation is correct.&lt;/p&gt;

&lt;h2 id=&quot;end-to-end-tests&quot;&gt;End-to-End tests&lt;/h2&gt;

&lt;p&gt;By end-to-end tests, I mean both UI and API tests for the system. The main thing in such tests is that we work with the system as a user. You can call such tests black-box if you want.&lt;/p&gt;

&lt;p&gt;Once you master the Selenium Webdriver’s API and know how to use Page Object (and other) patterns, implementing end-to-end tests becomes very easy. 
Of course, there can be exceptions: very complex and tricky logic, exotic browsers, or non-standard APIs. 
Creating new UI tests is trivial for a developer (compared to unit and integration tests). That is why everyone believes that end-to-end tests are the easiest.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220717/end-to-end.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;But the thing is that automated testing is not only about implementing new tests. It is also the maintenance of such tests. It is debugging and fixing. Here lies the biggest pitfall (almost an iceberg) in the perception of end-to-end testing.&lt;/p&gt;

&lt;p&gt;A LOT of external and internal factors affect the performance and stability of such tests:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;databases&lt;/strong&gt; can perform slow replication and return inconsistent data&lt;/li&gt;
  &lt;li&gt;hundreds or thousands of backend &lt;strong&gt;microservices&lt;/strong&gt; can stop working at any time (causing cascading problems)&lt;/li&gt;
  &lt;li&gt;critical services may receive data from the &lt;strong&gt;message broker&lt;/strong&gt; (e.g., Kafka) with a delay&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;third-party services&lt;/strong&gt; can also work unstable or be completely unavailable&lt;/li&gt;
  &lt;li&gt;the system may be under the influence of an external &lt;strong&gt;DDoS attack&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;load balancers&lt;/strong&gt; and &lt;strong&gt;caches&lt;/strong&gt; can also be unstable&lt;/li&gt;
  &lt;li&gt;the &lt;strong&gt;web or mobile applications&lt;/strong&gt; can work differently (depending on the phone model or the browser version)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;requests from the browser in the tests&lt;/strong&gt; may be processed more slowly  than from the actual user&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;the test framework&lt;/strong&gt; can be erratic (especially if you run many tests in parallel)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;connections to containers&lt;/strong&gt; in Selenoid can also disappear for some reason&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;connection to device farm&lt;/strong&gt; can also be a point of instability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Considering all these hidden moving parts, the business, management, and even fellow testing team still expect &lt;strong&gt;almost 100% stability of UI tests.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But the reality is harsh. When any UI test fails - it needs to be &lt;strong&gt;isolated, analyzed, and carefully fixed&lt;/strong&gt;. If you have a dedicated automation team, those few brave engineers need not only understand at which point of the test the issue occurred. They need to isolate the problem and report it to the particular development team for a fix.&lt;/p&gt;

&lt;p&gt;Sometimes, the fix will be on the UI test or framework level. Sometimes it is a change in requirements or the urgent need to update the test data.&lt;/p&gt;

&lt;p&gt;But in many cases, the fix also can’t be done immediately, especially if the root cause is unclear and need time for investigation. The development team has its priorities and tasks. Ignorance of such failing tests and issues increases the risk of having a bug in production. But anyway - it is a question of how effectively to use end-to-end testing on the project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;As a test automation engineer, you don’t have control of the system and its dependencies. Here is your browser - and that’s it!&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;so-which-automation-tests-are-the-most-complicated&quot;&gt;So, which automation tests are the most complicated?&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220717/compare-levels.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I don’t say that some tests are redundant and do not bring value. I just want to state that after an initial learning effort, the implementation of unit and integration tests becomes a relatively easy task. That’s why we need to have more tests at these levels.&lt;/p&gt;

&lt;p&gt;UI tests can become a nightmare if they are flaky and slow. But it can slow the whole development and release process if the automation team is separate and there is no dedication to end-to-end tests from each development group.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;End-to-end tests can bring value or be the most complicated automated tests to maintain. It can be a huge source of frustration for automation engineers.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Do you expect stable UI tests for your automation team?&lt;/p&gt;</content><author><name>Oleksandr Romanov</name></author><summary type="html">Photo by GR Stocks on Unsplash</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://alexromanov.github.io/img/20220717/challenge.jpg" /><media:content medium="image" url="https://alexromanov.github.io/img/20220717/challenge.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Under The Hood: How Git works?</title><link href="https://alexromanov.github.io/2022/06/26/uth-1-how-git-works/" rel="alternate" type="text/html" title="Under The Hood: How Git works?" /><published>2022-06-26T06:00:00+00:00</published><updated>2022-06-26T06:00:00+00:00</updated><id>https://alexromanov.github.io/2022/06/26/uth-1-how-git-works</id><content type="html" xml:base="https://alexromanov.github.io/2022/06/26/uth-1-how-git-works/">&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/photos/scZjGeVXCq8?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditShareLink&quot;&gt;Sebastian Herrmann on Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finding a test engineer who would not have heard of version control systems is difficult nowadays. Some have worked (and work with quite “old”) - such as &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Subversion&quot;&gt;Subversion&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Mercurial&quot;&gt;Mercurial HG&lt;/a&gt;&lt;/strong&gt;, etc.&lt;/p&gt;

&lt;p&gt;But the vast majority of modern projects today use &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Git&quot;&gt;Git&lt;/a&gt;&lt;/strong&gt;. If you need to download a “fresh” version of the product code or automated tests, go to the Terminal (or GUI tool) and perform a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git fetch&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pull&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Learning the basic Git commands is not that hard. It is a bit more difficult to understand what &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;merge&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rebase&lt;/code&gt; are (and their difference).&lt;/p&gt;

&lt;p&gt;But few engineers look deeper - &lt;strong&gt;how does Git work “under the hood”&lt;/strong&gt;? Of course, you don’t have to know this to use Git. But I was still interested to understand. Plus, if you will be asked about Git internals at the interview - you will already know it! (But why ask such a question???).&lt;/p&gt;

&lt;p&gt;Welcome to the world of &lt;strong&gt;graphs&lt;/strong&gt; and &lt;strong&gt;hash functions&lt;/strong&gt;. You can learn about another application of hash functions - Merkle trees - in my &lt;strong&gt;&lt;a href=&quot;https://alexromanov.github.io/2022/06/19/bchain-test-7-merkle-tree/&quot;&gt;previous post&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;a-bit-of-git-theory&quot;&gt;A bit of Git theory&lt;/h2&gt;

&lt;p&gt;Let me remind you what a typical workflow with Git looks like:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Make a clone of a remote repository: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git clone https://somerepo&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Make a branch for your changes (fixes, tests, etc.): &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git checkout -b fix/autotests&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Write everything you want (Git will notice it but wait for your actions): &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git status&lt;/code&gt; returns “changes not staged for commit.”&lt;/li&gt;
  &lt;li&gt;Add files to staged area using: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git add&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Create a new commit: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit -m &quot;Fix autotests&quot;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Send prepared commit to a remote repository: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git push origin fix/autotests&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Pass the code review and merge the changes into the main branch: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git rebase&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git merge&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Send changes to the main branch from the local repository to the remote one: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git push origin main/master&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Remove the branch, if necessary: ​​&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git branch -D fix/autotests&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-structure-of-git&quot;&gt;The structure of Git&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220626/1.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;There are three types of objects that Git takes care of:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Commit&lt;/strong&gt; - contains the author of the commit, date, message, and pointer to the tree of changes. Also, each commit has one (or more) parent commit;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tree&lt;/strong&gt; - contains a pointer to other trees and specific blob objects;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Blob&lt;/strong&gt; - specific data (source code files, pictures, videos, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So what is the structure of the Git repository? This is a data structure called a &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Graph_(abstract_data_type)&quot;&gt;graph&lt;/a&gt;&lt;/strong&gt;. Or, more specifically - a &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Directed_acyclic_graph&quot;&gt;directed acyclic graph&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where can all this information be found?&lt;/strong&gt; When you clone a repository or create a new one, all this data will be stored in a hidden &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git&lt;/code&gt; directory in the project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What are tags and branches?&lt;/strong&gt; These are just pointers to a commit object.&lt;/p&gt;

&lt;h2 id=&quot;what-happens-during-git-init&quot;&gt;What happens during git init?&lt;/h2&gt;

&lt;p&gt;Let’s create a new repository in the directory - &lt;strong&gt;testrepo&lt;/strong&gt;. To do this, go to the folder and run the command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git init&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As a result, we get a lot of exciting things in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git&lt;/code&gt; directory:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220626/2.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;making-a-first-commit&quot;&gt;Making a first commit&lt;/h2&gt;

&lt;p&gt;Create a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;README.md&lt;/code&gt; file with any content and add it to the first git add. Now, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git&lt;/code&gt; looks like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220626/3.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We can see that Git created some new folders and files: &lt;strong&gt;3a&lt;/strong&gt; folder with a strange file inside.&lt;/p&gt;

&lt;p&gt;It results from the &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/SHA-1&quot;&gt;SHA-1 hash function&lt;/a&gt;&lt;/strong&gt; running on our README.md file. (You can read about the hash functions in &lt;strong&gt;&lt;a href=&quot;https://alexromanov.github.io/2022/05/01/bchain-testing-1-hashing/&quot;&gt;one&lt;/a&gt;&lt;/strong&gt; of my previous blog posts)&lt;/p&gt;

&lt;p&gt;Git has a separate team to help us with research: git cat-file.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t&lt;/code&gt; argument indicates the type of object&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-p&lt;/code&gt; argument shows the contents of the object&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; You may specify not the full hash of the object - but only the first six characters (&lt;em&gt;Keep in mind that you must also set the subfolder characters - in our case it is 3a. And then the first four characters of the object&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;In our case, the results will be as follows:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220626/4.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;When we added the README.md file to the staging area, Git also created a &lt;strong&gt;blob&lt;/strong&gt; object under the hood.&lt;/p&gt;

&lt;p&gt;Next, create a new commit with the file and look at the contents of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git&lt;/code&gt; directory again.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220626/5.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;As you can see, now we have not one new object but three. One we have already seen (starts with &lt;strong&gt;3ae2e2&lt;/strong&gt;). What about others?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220626/6.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;232c6a&lt;/strong&gt; is a tree object. It points to a blob object (we also see the hash of this object and the name). &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;100644&lt;/code&gt; is the permissions for this file.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220626/7.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;85ac4e&lt;/strong&gt; is a commit object. It points to an object of type tree (we see its complete hash) and indicates the author and the text of the commit.&lt;/p&gt;

&lt;h2 id=&quot;more-commits&quot;&gt;More commits&lt;/h2&gt;

&lt;p&gt;To complete the task - add another file and correct &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;README.md&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220626/8.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git&lt;/code&gt; contains new objects:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220626/9.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;First, we have a new commit object that contains a pointer to a new tree object, &lt;strong&gt;f71e00a8f2d3eff8348ad77149932dc11ab9e717&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In addition, in this commit we have parent &lt;strong&gt;85ac4e3d6dba749723b69ce6f655c5acf5a00782&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220626/10.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If we look at the new tree, we will see that it now points to two objects of type blob: a new file and a modified README.md.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220626/11.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Interestingly, the blob object for README.md already has a different hash. The reason is that we changed the file’s text - so the hash value also changed. But the old blob file also remained available (3ae2e2)!&lt;/p&gt;

&lt;h3 id=&quot;a-few-words-about-the-branches&quot;&gt;A few words about the branches&lt;/h3&gt;

&lt;p&gt;Finally, I want to show what happens when we create new branches in Git.&lt;/p&gt;

&lt;p&gt;Let’s run the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git checkout -b fix/autotests&lt;/code&gt; command and look in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220626/12.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If we look at the contents of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git/refs/heads/fix/autotests&lt;/code&gt; file, we will see that it points to our second commit!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220626/13.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h2&gt;

&lt;p&gt;As you can see - Git under the hood looks not so complicated. Especially when you already know what hashing is.&lt;/p&gt;

&lt;p&gt;Therefore, the next time you see unknown numbers and letters near commits, you will know that it is a just &lt;strong&gt;hash&lt;/strong&gt; value from objects.&lt;/p&gt;</content><author><name>Oleksandr Romanov</name></author><summary type="html">Photo by Sebastian Herrmann on Unsplash</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://alexromanov.github.io/img/20220626/branch.jpg" /><media:content medium="image" url="https://alexromanov.github.io/img/20220626/branch.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Blockchain for Test Engineers: Merkle Trees</title><link href="https://alexromanov.github.io/2022/06/19/bchain-test-7-merkle-tree/" rel="alternate" type="text/html" title="Blockchain for Test Engineers: Merkle Trees" /><published>2022-06-19T06:00:00+00:00</published><updated>2022-06-19T06:00:00+00:00</updated><id>https://alexromanov.github.io/2022/06/19/bchain-test-7-merkle-tree</id><content type="html" xml:base="https://alexromanov.github.io/2022/06/19/bchain-test-7-merkle-tree/">&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/photos/peOp2E3Zukk?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditShareLink&quot;&gt;Camille Brodard on Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This blog post is a part of &lt;a href=&quot;https://alexromanov.github.io/2022/04/24/blockchain-testing-mindmap/&quot;&gt;&lt;strong&gt;“Blockchain for Test Engineers”&lt;/strong&gt;&lt;/a&gt; series.&lt;/p&gt;

&lt;p&gt;In previous articles, we have already discussed &lt;strong&gt;&lt;a href=&quot;https://alexromanov.github.io/2022/05/01/bchain-testing-1-hashing/&quot;&gt;hash functions&lt;/a&gt;&lt;/strong&gt; and their usage. Today I propose to learn about an exciting data structure built using hashes - &lt;strong&gt;Merkle Tree&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;blockchain-and-transactions&quot;&gt;Blockchain and transactions&lt;/h2&gt;
&lt;p&gt;A &lt;strong&gt;&lt;a href=&quot;https://alexromanov.github.io/2022/06/05/bchain-test-what-is-blockchain/&quot;&gt;blockchain&lt;/a&gt;&lt;/strong&gt; is a chain of data blocks connected cryptographically (each subsequent block points to the previous one).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220619/blockchain.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In addition, each block stores a lot of other interesting information: the hash of the block itself, the number of transactions, the complexity of the mining algorithm, and more. But most importantly - each block contains a set of validated transactions.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220619/block.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;But how can a user verify that a transaction is inside the block? Wasn’t it changed during the mining phase?&lt;/p&gt;

&lt;p&gt;In the simplest case, the user must download the entire blockchain to his computer and check the required blocks. Each block takes up, on average, about 1MB. Therefore, the transaction verification process can take a long time (and requires hard disk space too).&lt;/p&gt;

&lt;p&gt;But there is a way to check transactions quickly and with a much smaller data set than the whole block? The answer is yes - it is &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Merkle_tree&quot;&gt;Merkle tree&lt;/a&gt;&lt;/strong&gt; data structure.&lt;/p&gt;

&lt;h2 id=&quot;what-is-merkle-tree&quot;&gt;What is Merkle Tree?&lt;/h2&gt;
&lt;p&gt;Imagine that we have eight transactions ready to be included in the block:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220619/trxs.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Apply hash functions to each transaction:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220619/trxhashes.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Let’s concatentate each pair of hashes and then hash the result:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220619/round2.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We will continue the pairing and hashing processes until we get a single value:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220619/tree.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The resulting binary tree is called a &lt;strong&gt;Merkel Tree&lt;/strong&gt;. The last hash obtained is the tree’s root (Merkle Root). This root is also a part of the header of each block in the Bitcoin blockchain.&lt;/p&gt;

&lt;p&gt;Other parts of the Merkle Tree are &lt;strong&gt;non-leaf nodes&lt;/strong&gt; and &lt;strong&gt;leaf nodes.&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;what-is-the-meaning-of-the-merkle-tree&quot;&gt;What is the meaning of the Merkle Tree?&lt;/h2&gt;
&lt;p&gt;The advantage of organizing transactions in the form of Merkle Tree manifests when we check the integrity of the transaction.&lt;/p&gt;

&lt;p&gt;In a simple case you can download all eight transactions, then generate a leaf nodes and recreate the process of creating a tree from scratch. And then - compare the resulting root of the tree with the one stored inside the block.&lt;/p&gt;

&lt;p&gt;We can do it for a dozen transactions. But if there are &lt;strong&gt;thousands&lt;/strong&gt; of transactions? Or millions, or maybe more? For example, some projects can contain &lt;strong&gt;billions&lt;/strong&gt; of Merkle Tree leaves. So to re-create the tree, you need to compute a vast amount of hashes with the &lt;strong&gt;O(n) complexity&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Merkle Proofs&lt;/strong&gt; allows you to mathematically check the integrity of the transaction without the need to download and recreate all transactions. You need to perform much fewer operations.&lt;/p&gt;

&lt;p&gt;For example, we need to check &lt;strong&gt;transaction 2&lt;/strong&gt;. In this case, we need to have Merkle Tree root and Merkle Proof for this transaction:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220619/proof.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In our example, the proof contains only 3 hashes and another 4 hashes we need to calculate to get a Merke Root. Otherwise, we will need to download 8 transactions and calculate 15 hashes.&lt;/p&gt;

&lt;p&gt;Instead of donwloading n transactions, we need to download &lt;strong&gt;O(log n)&lt;/strong&gt;-sized Merkle Proof and also - Merkle Root.&lt;/p&gt;

&lt;p&gt;In the Bitcoin blockchain, if we need to verify that transaction is indeed in the block, we need to download the block header (80 bytes instead of 1MB block) and then request Merkle Proof for a specific transaction. As a result, we can unambiguously check the integrity of the transaction with much lower resource costs.&lt;/p&gt;

&lt;p&gt;Merkle Tree is used in Bitcoin’s “light” clients (Simple Payment Verification nodes) to quickly validate if transaction belongs to a particular block.&lt;/p&gt;

&lt;h2 id=&quot;where-you-can-find-merkle-trees&quot;&gt;Where you can find Merkle Trees?&lt;/h2&gt;
&lt;p&gt;It turns out, that Merkle Trees are used in many modern systems:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Git_(software)&quot;&gt;Git&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Mercurial&quot;&gt;Mercurial&lt;/a&gt;&lt;/strong&gt; version control systems - for storing versions of data)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Apache_Cassandra&quot;&gt;Cassandra&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Dynamo_(storage_system)&quot;&gt;DynamoDB&lt;/a&gt;&lt;/strong&gt; - for detecting inconsistencies between replicas and minimize the amount of data transferred&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Bitcoin&quot;&gt;Bitcoin&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Ethereum&quot;&gt;Ethereum&lt;/a&gt;&lt;/strong&gt; blockchains - for validating integrity of transactions&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/InterPlanetary_File_System&quot;&gt;IPFS&lt;/a&gt;&lt;/strong&gt; file system&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Oleksandr Romanov</name></author><summary type="html">Photo by Camille Brodard on Unsplash</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://alexromanov.github.io/img/20220619/roots.jpg" /><media:content medium="image" url="https://alexromanov.github.io/img/20220619/roots.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">High Tech - Low Test or Problems with Modern Testing</title><link href="https://alexromanov.github.io/2022/06/12/high-tech-low-test/" rel="alternate" type="text/html" title="High Tech - Low Test or Problems with Modern Testing" /><published>2022-06-12T06:00:00+00:00</published><updated>2022-06-12T06:00:00+00:00</updated><id>https://alexromanov.github.io/2022/06/12/high-tech-low-test</id><content type="html" xml:base="https://alexromanov.github.io/2022/06/12/high-tech-low-test/">&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/photos/71SHXwBLp5w?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditShareLink&quot;&gt;Leyre on Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have been working in test automation and development for more than ten years. I’ve seen good projects, and I’ve seen awful ones.&lt;/p&gt;

&lt;p&gt;In this blog post, I want to highlight the problems I see in the testing industry and how we all can fix it. (You may have a different experience - so let’s share it in the comments!). This is a text version of &lt;strong&gt;&lt;a href=&quot;https://youtu.be/jigPyy6wSfk&quot;&gt;my talk that I gave at Abu Dhabi MoT meetup at the beginning of 2022&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;what-has-changed-in-the-industry-in-10-years&quot;&gt;What has changed in the industry in 10 years&lt;/h2&gt;

&lt;p&gt;Over the past ten years, we have witnessed a significant technological boost - driverless cars, artificial intelligence, AR / VR, blockchain, drones, and robots. Much testing and test automation moved from the desktop to the web and mobile devices.&lt;/p&gt;

&lt;p&gt;From Waterfall models, many businesses went to Agile and Scrum.&lt;/p&gt;

&lt;p&gt;From big and costly tools for writing automation tests, we have moved to small, flexible, and, most importantly - free libraries and tools. Now we have intelligent reporting systems and tests in Docker containers. Running thousands of tests in parallel in the clouds now is not so expensive.&lt;/p&gt;

&lt;p&gt;But at the same time, many things and statements have remained unchanged.&lt;/p&gt;

&lt;p&gt;Here are some of the endless topics that are constantly raging among testers:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;“Manual testing is dead!”&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;“Let’s automate everything! Through UI - that’s the best!”*&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;“SDET is the peak of the evolution of a test engineer! I want to be like Google!”&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;“I can’t get a job in development, so I will work for a year or so as a tester and then try again.”&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;“Salaries of testers - at the bottom!”&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;“Test engineering is a job for low-skilled professionals!”&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But why is there such a situation in the industry? Could the problems be something else? What issues do I see?&lt;/p&gt;

&lt;h2 id=&quot;problems-with-modern-testing&quot;&gt;Problems with modern testing&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220612/problems.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/photos/LrlyZzX6Sws?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditShareLink&quot;&gt;Karla Hernandez on Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I will divide the problems into two large groups.&lt;/p&gt;

&lt;h3 id=&quot;the-pursuit-of-technology&quot;&gt;The pursuit of technology&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Concentration only on short-term goals.&lt;/strong&gt; Many engineers prefer only quick solutions. Such an attitude to automation tests is prevalent. The engineers quickly wrote “something” without any thoughts of maintainability and ran out to a new project.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Resume-driven development.&lt;/strong&gt; Many testers only consider jobs and projects as a way to get a fancy new line in CV. There is nothing about deepening the skills and solving business issues with testing and automation.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;The green pipelines cult.&lt;/strong&gt; In this case, test engineers who have successfully included tests into their CICD pipelines begin to be obsessed with making tests green all the time. Such obsession often results in ignoring or even removing unstable tests (which leads to ignoring the problems behind ignored tests).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Framework-oriented automation.&lt;/strong&gt; In some projects, engineers are so eager to write the perfect framework that they forget about the tests themselves. As a result, we have 3-6 months of development without tests!. But for the customer, the absence of tests is a direct indicator of the lack of benefits from automation.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Search for silver bullets.&lt;/strong&gt; Some engineers create a successful framework for one project (and for one context) and then start pulling it into all the others as a “perfect solution.” It is not reusability; it only applies one hammer to all the nails and bolts.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;insufficient-level-of-skills-and-knowledge&quot;&gt;Insufficient level of skills and knowledge&lt;/h3&gt;

&lt;p&gt;The lack of knowledge can take multiple forms.&lt;/p&gt;

&lt;h4 id=&quot;technical-knowledge&quot;&gt;Technical knowledge&lt;/h4&gt;
&lt;p&gt;In interviews, senior candidates often quickly answer any questions about testing. They can draw a “testing pyramid or any figure you want” for you, tell you all the test design techniques in the world, and write the perfect bug report. But candidates quickly lose confidence when you ask questions about fundamental technical aspects (such as how HTTP or networks work).&lt;/p&gt;

&lt;p&gt;You can tell me that not every project requires specific knowledge. That’s true. But test engineers should know (or at least be aware of) the fundamental technical knowledge. Ideally, a little bit deeper than the first link in the Google search.&lt;/p&gt;

&lt;p&gt;90% of modern systems work with the network in one way or another, send messages or requests, and use the database or distributed storage. Multiple layers of abstractions can cover it - but in a nutshell - it all works similarly.&lt;/p&gt;

&lt;h4 id=&quot;programming-and-architecture&quot;&gt;Programming and architecture&lt;/h4&gt;
&lt;p&gt;Some test engineers still believe that learning programming is complicated and unnecessary. Let the programmers write the code!&lt;/p&gt;

&lt;p&gt;The other part is those who have learned to code a bit but concentrate their efforts only on the UI tests. The world outside of these tests does not seem to exist.&lt;/p&gt;

&lt;p&gt;Knowledge of system architecture and how they work is a scarce skill among test engineers. All this is considered work for experienced “bearded” architects or only senior developers with dozen years of experience.&lt;/p&gt;

&lt;p&gt;But without knowing how the system works inside and with each other, it is easy to miss a lot of critical errors. On the other hand, the lack of technical knowledge will make it hard to describe such issues in a bug report.&lt;/p&gt;

&lt;p&gt;I’m not saying that without knowledge of the components of the system, it is impossible to point out lousy testability. As a result, we continue to write fragile XPath locators because no one has added IDs for elements.&lt;/p&gt;

&lt;h4 id=&quot;knowledge-of-business-and-product&quot;&gt;Knowledge of business and product&lt;/h4&gt;
&lt;p&gt;Of course, it all depends on the project. There are some projects where a testing team works as if on a factory line: get the build, test it and pass it to the next unit (without asking any questions).&lt;/p&gt;

&lt;p&gt;Test engineers are significantly lacking in product knowledge. Few engineers work with users or with customer support. 
But those people can provide helpful information about the riskiest parts of the application or give feedback on the usability system.&lt;/p&gt;

&lt;p&gt;Even fewer test and automation engineers think about how their work affects business. Do those automation tests save the company money? Or provide feedback faster than the manual testing?&lt;/p&gt;

&lt;h4 id=&quot;personal-development-of-engineers&quot;&gt;Personal development of engineers&lt;/h4&gt;
&lt;p&gt;Regarding personal development, there are two significant groups of engineers exist:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;“Why should I learn to program (any other skill)? That will make me a less skilled tester!”&lt;/li&gt;
  &lt;li&gt;“I allegedly want to study, but I’m waiting for my one-year feedback. My manager or test lead will come and tell me what I need to learn.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But here lies the most critical point. &lt;strong&gt;ONLY YOU ARE RESPONSIBLE FOR THE PERSONAL DEVELOPMENT OF SKILLS, KNOWLEDGE, AND CAREER!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your manager (or anyone else on the Internet) will not be able to create a map of your skills for you. Only you know your strengths and weaknesses. Only you know (or guess) what gaps you have in your knowledge. Only you can understand how to gain that knowledge and reach a new level (and get that dream boost).&lt;/p&gt;

&lt;p&gt;The manager can only adjust your plan and indicate the company’s resources: the budget for attending conferences or other developments.&lt;/p&gt;

&lt;h2 id=&quot;a-vicious-circle-of-uncertainty&quot;&gt;A vicious circle of uncertainty&lt;/h2&gt;
&lt;p&gt;So what questions does an average test engineer usually ask himself?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;“I can’t write code - I’m not a developer …”&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;“Who am I to talk to an Architect about the architecture or testability of system components?”&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;“The DevOps team have turned off unstable tests in the pipeline - well, they know more about how it should be …”&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;“The manager keeps asking me: what exactly are you testing? Why is that? And that?”&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;“Business is just trying to cut the costs and fire the whole department of unnecessary testers ….”&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;“How do I even know what problems our users have?”&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a result, most test engineers fall into a circle of uncertainty.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220612/cycle.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Testers cannot correctly prove their benefits to the team, other engineers, management, and business. In such cases, it is hard for a tester to build trust and confidence inside the team;&lt;/li&gt;
  &lt;li&gt;Demotivation of test engineers is growing. The idea to switch to software development or management grew along with demotivation.&lt;/li&gt;
  &lt;li&gt;Many experienced and senior engineers leave the testing industry. Cases of successful testers are becoming fewer and fewer. Cases when test engineers influence the product and processes and make technical improvements - can be counted on your fingers. Achievements and stories at conferences come down to “well, we got this framework or this tool for test management - now it’s all  beautiful.” There is a lack of people who can write new libraries and tools. There is no one to test complex and scientific software. There is no one to do research in the field of testing;&lt;/li&gt;
  &lt;li&gt;The industry continues to think that a tester is someone who “just pushes buttons and does almost nothing.” Young test engineers see the same picture but are even more demotivated;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;how-to-change-the-situation-for-the-better&quot;&gt;How to change the situation for the better&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Prepare a plan for your professional development.&lt;/strong&gt; What skills to acquire, what to learn, and how to use those skills at work. If you can gain knowledge and skills in the company - that’s excellent! If not - look for another project or company. There is always a choice - and it is in your hands.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Learn to program.&lt;/strong&gt; I’m not talking about skills at the level of a senior developer. But the ability to write a script can remove a lot of monotonous work from the deployment or configuration. Reading and understanding someone else’s code gives a better understanding of how the system works in general and which cases are not yet covered.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Deepen your knowledge of application and systems architecture.&lt;/strong&gt; Start with the system you are testing now. Decompose it. Disassemble architectural diagrams. Think about how and where an individual component may “fall” and how the system will respond. Talk to your architect.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;If you are creating scripts or automation tests, always ask yourself: who and how will use my code (tests)?&lt;/strong&gt; Is it written clear enough? Is there a detailed report? How easy will it be for a new engineer to understand the code?&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Learn how users work with your system.&lt;/strong&gt; What is your product business model? What are the riskiest parts? This information will help you test what is vital to the user and save money for the business.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;</content><author><name>Oleksandr Romanov</name></author><summary type="html">Photo by Leyre on Unsplash</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://alexromanov.github.io/img/20220612/hightech.jpg" /><media:content medium="image" url="https://alexromanov.github.io/img/20220612/hightech.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Blockchain for Test Engineers: What is blockchain?</title><link href="https://alexromanov.github.io/2022/06/05/bchain-test-what-is-blockchain/" rel="alternate" type="text/html" title="Blockchain for Test Engineers: What is blockchain?" /><published>2022-06-05T06:00:00+00:00</published><updated>2022-06-05T06:00:00+00:00</updated><id>https://alexromanov.github.io/2022/06/05/bchain-test-what-is-blockchain</id><content type="html" xml:base="https://alexromanov.github.io/2022/06/05/bchain-test-what-is-blockchain/">&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/photos/HOrhCnQsxnQ?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditShareLink&quot;&gt;Robynne Hu on Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the sixth blog post in the &lt;a href=&quot;https://alexromanov.github.io/2022/04/24/blockchain-testing-mindmap/&quot;&gt;&lt;strong&gt;“Blockchain for Test Engineers”&lt;/strong&gt;&lt;/a&gt; series.&lt;/p&gt;

&lt;p&gt;We have explored concepts from &lt;strong&gt;&lt;a href=&quot;https://alexromanov.github.io/2022/05/01/bchain-testing-1-hashing/&quot;&gt;hashing&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href=&quot;https://alexromanov.github.io/2022/05/08/bchain-testing-2-encryption/&quot;&gt;encryption&lt;/a&gt;&lt;/strong&gt;, and &lt;strong&gt;&lt;a href=&quot;https://alexromanov.github.io/2022/05/22/bchain-test-4-distributed-systems/&quot;&gt;distributed systems&lt;/a&gt;&lt;/strong&gt; in the previous posts. Now it’s time to apply this knowledge and understand what blockchain is.&lt;/p&gt;

&lt;p&gt;When I first started to google on this topic, I found many articles, videos, and even courses dedicated to the blockchain. But all these resources eventually fell into two categories: &lt;strong&gt;too superficial&lt;/strong&gt; or &lt;strong&gt;too deep.&lt;/strong&gt; There was nothing in between.&lt;/p&gt;

&lt;p&gt;Today I want to briefly, technically, and with pictures, tell you what blockchain is and how it works. We will save questions of advantages and disadvantages and other deep technical details for another time.&lt;/p&gt;

&lt;h2 id=&quot;why-do-we-need-a-blockchain-if-there-is-already-a-bank&quot;&gt;Why do we need a blockchain if there is already a bank?&lt;/h2&gt;
&lt;p&gt;Each of us uses the services of a bank and makes transactions from a card or account. We can see the list of transactions by going to the bank’s application. (Or by requesting in paper form as a reference).&lt;/p&gt;

&lt;p&gt;Each transaction contains information about the time and purpose of the payment. In addition, we can also see the recipient of each transaction.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220605/banking.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Two parties can see this list of transactions - you, as a client of the bank, and the bank itself. The bank “securely” stores the information about your transactions on the bank’s servers. By receiving this list, you trust the bank that it did not inadvertently manipulate your balance.&lt;/p&gt;

&lt;p&gt;In addition, the bank has every right to freeze your funds if it considers them suspicious.&lt;/p&gt;

&lt;p&gt;Don’t you think that requires a lot of trust and single-handedly manages your accounts?&lt;/p&gt;

&lt;h2 id=&quot;what-is-blockchain&quot;&gt;What is blockchain?&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://bitcoin.org/bitcoin.pdf&quot;&gt;The original idea of blockchain&lt;/a&gt;&lt;/strong&gt; emerged as an alternative to regular bank payments. (Of course, the blockchain is not only used for financial transactions - but let’s start with them).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220605/blockchain.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Instead of the bank servers, we have a peer-to-peer network of thousands of computers. Each node in the network contains an entire history of transactions made by all users in the system. As transaction data is stored on multiple nodes simultaneously, nobody can “freeze” your money or delete transaction history.&lt;/p&gt;

&lt;p&gt;The nodes in the network share information about transactions with each other. So the state of the transaction history is synchronized.&lt;/p&gt;

&lt;p&gt;Another key difference from regular banking is that transaction history on the blockchain cannot be changed and is visible to anyone.&lt;/p&gt;

&lt;h2 id=&quot;how-does-it-work-technically&quot;&gt;How does it work technically?&lt;/h2&gt;

&lt;p&gt;We can think about transaction data on each node as a form of a distributed ledger (or, in other words - an extensive distributed database of data). The ledger here means that information contains a few critical components: who send the money, to whom, and which amount.&lt;/p&gt;

&lt;p&gt;The ledger is a set of identical blocks (that are linked cryptographically) and distributed across all nodes in a peer-to-peer network.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220605/block.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Each block has four fields: block size, block headers, transaction counter, and transactions.&lt;/p&gt;

&lt;p&gt;The block headers contain:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;the block version;&lt;/li&gt;
  &lt;li&gt;the hash of the previous block. The blockchain is named so - it is a chain of blocks;&lt;/li&gt;
  &lt;li&gt;the Merkle root hash of all transactions included in the block;&lt;/li&gt;
  &lt;li&gt;timestamp;&lt;/li&gt;
  &lt;li&gt;difficulty target;&lt;/li&gt;
  &lt;li&gt;nonce;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;why-store-the-hash-of-the-previous-block&quot;&gt;Why store the hash of the previous block?&lt;/h3&gt;
&lt;p&gt;Here is the beauty and power of the hashing. It helps to ensure the consistency of the blockchain and prevent changes.&lt;/p&gt;

&lt;p&gt;Imagine that an attacker wants to change the content of a transaction that belongs to block one. The change in the transaction will change the hash of the transaction. Then the change of transaction hash will change the hash of block one. If an attacker wants to spread a new block across the network, he must modify the other blocks after block one. (because they are linked).&lt;/p&gt;

&lt;p&gt;In addition - the attacker then needs to spread a new chain of blocks (modified) across all the nodes and force everybody to use an updated version of the chain. Given the number of nodes in the network, it can be a challenging and expensive task. 
Why expensive? An attacker needs to re-create many blocks, which takes resources and time.&lt;/p&gt;

&lt;p&gt;Every block and every transaction are digitally signed. Any network user can verify this signature and ensure there were no fakes. So it will be suspicious if all blocks in the “attackers chain” are signed by a single user.&lt;/p&gt;

&lt;h2 id=&quot;how-user-creates-a-new-transaction&quot;&gt;How user creates a new transaction&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220605/create_transaction.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The client forms a transaction using the command line or special applications (crypto wallets). Inside a transaction, there are sender, recipient, and the transfer amount. In addition, he sets the transaction fee. (We will see different transaction models in the upcoming blog posts).&lt;/p&gt;

&lt;p&gt;In our example, client one connects to node one and sends trx1, and client two sends trx2 to node three. The client has no control over which node it connects to and where it sends the transaction.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220605/prepare_transaction.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Each network node collects incoming transactions for some time in its local storage (MemPool). Nodes exchange incoming transactions with each other (but it is not mandatory. Nodes can be at any place in the world and have different configurations - so the view of the network can differ from node to node).&lt;/p&gt;

&lt;p&gt;From time to time, the node forms a new block of transactions. The node signs the block. In addition, to finally create and distribute a valid block in the network, the node must participate in the Proof-Of-Work consensus.&lt;/p&gt;

&lt;h2 id=&quot;mining-new-blocks&quot;&gt;Mining new blocks&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220605/mining_block.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Each node with a new potential block starts a race with the other nodes who prepared a candidate block. 
The ultimate goal of each miner node is to make a special kind of block hash. For example, it can be a certain amount of zeroes at the beginning of the hash value.&lt;/p&gt;

&lt;p&gt;The miner adds a number (nonce) to the block to find such a hash. If the hash is not equal to the desired one - the miner increments the nonce and does it again. This task is simple but resource-intensive - you need to make a tremendous amount of trial and error by brute force. This process is called mining.&lt;/p&gt;

&lt;p&gt;The first node that finds the correct nonce and sends the block to the network - receives a reward in coins plus optional fees from each transaction. The reward is not immediately accessible to the user but only after adding some amount of new blocks.&lt;/p&gt;

&lt;h2 id=&quot;block-validation&quot;&gt;Block validation&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220605/validate_block.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;When a node finds such a nonce, it sends a new block to other nodes in the network. The node that receives the new block validates it and all transactions inside.&lt;/p&gt;

&lt;p&gt;What is checked inside a block:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;block structure&lt;/li&gt;
  &lt;li&gt;block header hash is equal&lt;/li&gt;
  &lt;li&gt;block timestamp&lt;/li&gt;
  &lt;li&gt;block size&lt;/li&gt;
  &lt;li&gt;the first transaction is a coinbase? (Coinbase transaction transfers the reward to the miner - it is always first in the block)&lt;/li&gt;
  &lt;li&gt;all transactions within the block&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If everything is in order with the block - it starts to spread over the network as a new valid block.&lt;/p&gt;

&lt;h2 id=&quot;block-propagation&quot;&gt;Block propagation&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220605/propagate_block.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Sooner or later, nodes will distribute the new block over the network using some protocol (for example, it can be &lt;strong&gt;&lt;a href=&quot;https://alexromanov.github.io/2022/05/29/bchain-test-5-p2p-gossip-protocols/&quot;&gt;Gossip protocol&lt;/a&gt;&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;In Bitcoin, a new block appears on the network every 10 minutes (the internal mining algorithm checks the complexity of the mining for all peers and adjusts it every 2048 blocks). But this does not mean at all that your transaction will be in the block in 10 minutes. But more on that next time.&lt;/p&gt;

&lt;p&gt;After some time, each node in the network gets the latest mined block. In parallel, other nodes can mine the subsequent candidate blocks.&lt;/p&gt;

&lt;h2 id=&quot;what-you-need-to-consider-when-testing-the-blockchain&quot;&gt;What you need to consider when testing the blockchain&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;the blockchain networks are huge&lt;/li&gt;
  &lt;li&gt;the blockchain networks are always in a working state&lt;/li&gt;
  &lt;li&gt;each change in the network affects many users&lt;/li&gt;
  &lt;li&gt;you can’t modify the data once saved on the blockchain&lt;/li&gt;
  &lt;li&gt;the information you save on-chain during testing is visible to anyone&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope that now you have a general understanding of the blockchain. We will gradually delve into different parts of this enormous system and see which thing we can test in the following blog posts.&lt;/p&gt;</content><author><name>Oleksandr Romanov</name></author><summary type="html">Photo by Robynne Hu on Unsplash</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://alexromanov.github.io/img/20220605/bch.jpg" /><media:content medium="image" url="https://alexromanov.github.io/img/20220605/bch.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Blockchain for Test Engineers: P2P networks and Gossip protocol</title><link href="https://alexromanov.github.io/2022/05/29/bchain-test-5-p2p-gossip-protocols/" rel="alternate" type="text/html" title="Blockchain for Test Engineers: P2P networks and Gossip protocol" /><published>2022-05-29T06:00:00+00:00</published><updated>2022-05-29T06:00:00+00:00</updated><id>https://alexromanov.github.io/2022/05/29/bchain-test-5-p2p-gossip-protocols</id><content type="html" xml:base="https://alexromanov.github.io/2022/05/29/bchain-test-5-p2p-gossip-protocols/">&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/photos/ahi73ZN5P0Y?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditShareLink&quot;&gt;Federico Beccari on Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the fifth blog post in the &lt;a href=&quot;https://alexromanov.github.io/2022/04/24/blockchain-testing-mindmap/&quot;&gt;&lt;strong&gt;“Blockchain for Test Engineers”&lt;/strong&gt;&lt;/a&gt; series.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Blockchain&lt;/strong&gt; is not a usual distributed system. It is a peer-to-peer network of nodes that communicates with each other.&lt;/p&gt;

&lt;p&gt;Today we will have a brief info on what peer-to-peer network is, why it is used in building distributed systems. Additionally, we will take a look at the way how new messages are propagated in the peer-to-peer networks.&lt;/p&gt;

&lt;h2 id=&quot;the-ways-how-networks-can-be-organized&quot;&gt;The ways how networks can be organized&lt;/h2&gt;

&lt;h3 id=&quot;client-server-model&quot;&gt;Client-Server model&lt;/h3&gt;

&lt;p&gt;This is a very common way for us to organize networks. It is a very familiar model for any test engineer working on WEB or mobile applications.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220529/clientserver.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This type of organization allocates one (or more) nodes that have a &lt;strong&gt;server&lt;/strong&gt; role. Other nodes are &lt;strong&gt;clients&lt;/strong&gt;. Clients make requests to the server using various communication protocols (HTTP, RPC, etc). The &lt;strong&gt;server&lt;/strong&gt; processes the request and responds to the &lt;strong&gt;client&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Despite of fact, that this way of system organization is a very widespread - it has it’s own problems. 
The main disadvantage of the model is that the server is somehow the only point of failure. Attackers can either take over the server and access information from customers (thereby interfering with the normal operation of the application). Or - with the help of DDoS attacks - make the server inaccessible to clients.&lt;/p&gt;

&lt;p&gt;One way to deal with a single point of failure is to use multiple servers in different parts of the world. This approach works but adds to the difficulty of replicating data between these servers. But about this - another time :).&lt;/p&gt;

&lt;h3 id=&quot;peer-to-peer-model&quot;&gt;Peer-to-Peer model&lt;/h3&gt;

&lt;p&gt;It turns out that you can avoid problems with a single point of failure, even without multiple servers.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220529/peer2peer.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Peer-to-peer&quot;&gt;Peer-to-Peer (P2P)&lt;/a&gt;&lt;/strong&gt; networks, each node (computer) is equal to another (logically). In fact, each node is a server and a client at the same time.&lt;/p&gt;

&lt;p&gt;Each node can provide data at the request of others, but also make requests and communicate with other nodes.&lt;/p&gt;

&lt;p&gt;Why it is hard to deal peer-to-peer networks:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;implementation of the reliable P2P system is a complex task;&lt;/li&gt;
  &lt;li&gt;configuration can be completely different from node to node;&lt;/li&gt;
  &lt;li&gt;nodes can be online or offline at any given point of time;&lt;/li&gt;
  &lt;li&gt;it is not possible to trust the message from other nodes (In client-server model you can trust server node at some degree);&lt;/li&gt;
  &lt;li&gt;additional effort needed for communication and coordination of messages in the system;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;well-known-p2p-examples&quot;&gt;Well-known P2P examples&lt;/h3&gt;
&lt;p&gt;As peer-to-peer technology has evolved, a lot of real-wolrd implementations have appeared.&lt;/p&gt;

&lt;p&gt;There are several generations of Peer-to-Peer networks:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;First generation.&lt;/strong&gt; Dedicated servers are still used as databases or node coordination servers. Examples: &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Napster&quot;&gt;Napster&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/EDonkey_network&quot;&gt;EDonkey2000&lt;/a&gt;&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Second generation.&lt;/strong&gt; There are no dedicated servers at all - all nodes are completely equal. Search and download protocols from other sites are not very effective. Example: &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Gnutella&quot;&gt;Gnutella&lt;/a&gt;&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Third generation.&lt;/strong&gt; The network is completely decentralized. Data retrieval is performed more efficiently and quickly - using an algorithm that uses distributed hash tables. Example: &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/BitTorrent_(software)&quot;&gt;BitTorrent&lt;/a&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;communication-in-a-peer-to-peer-networks&quot;&gt;Communication in a peer-to-peer networks&lt;/h2&gt;

&lt;p&gt;As we learn peer-to-peer networks more, one of the most fascinating questions may appear: “How do peer-to-peer nodes know about any updates or messages?”&lt;/p&gt;

&lt;p&gt;If we are dealing with a centralized system, the issue is solved very simply.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220529/centralized.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;All nodes are connected to the server node (Node 1) and receive information from it about any state changes. It does not matter whether the nodes themselves poll the server, or the server distributes new messages themselves. But if the server node stops working for some reason, the system will no longer be able to receive new updates.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220529/decentralized.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The task becomes more difficult when there is no dedicated node in the peer-to-peer system, which would be the “server” or “coordinator”. Each node is self-sufficient and equal. The only thing that can be done in such a system is to exchange messages.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Gossip_protocol&quot;&gt;Gossip protocol&lt;/a&gt;&lt;/strong&gt; helps to solve the problem when the network is decentralized and unreliable and when the nodes may also be unreliable.&lt;/p&gt;

&lt;h3 id=&quot;how-the-gossip-protocol-works&quot;&gt;How the Gossip protocol works&lt;/h3&gt;
&lt;p&gt;The Gossip protocol works in much the same way as gossip or epidemics spread in life. To do this, we use a &lt;strong&gt;&lt;a href=&quot;https://flopezluis.github.io/gossip-simulator/&quot;&gt;simulator&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Imagine that we have a peer-to-peer decentralized network of 20 nodes. As soon as one node receives a new message - it must spread it to all other participants. For each node, we can choose fanout values ​​- how many other nodes we can send messages to in one round. For example fanout = 4.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220529/initial.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In each round, the receiving node sends it to the other four participants.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220529/round1.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In the next round, each updated node sends message to other four randomly chosen nodes&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220529/round2.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Yes, rounds are repeated until all nodes have a message.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220529/round3.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Theoretically, you can calculate how many rounds it takes for all nodes in the system to receive messages and be synchronized. The number of rounds depends on the number of nodes and the fanout value.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220529/formula.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;There are multiple ways how node can get information about new updates and messages:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Push model&lt;/strong&gt; - nodes with new updates send them to other nodes&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Pull model&lt;/strong&gt; - nodes actively request updates from other nodes&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Push-pull model&lt;/strong&gt; - nodes can request for new and send updates&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;pros-and-cons-of-gossip-protocol&quot;&gt;Pros and cons of Gossip protocol&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Simplicity of the protocol&lt;/li&gt;
  &lt;li&gt;High fault-tolerance&lt;/li&gt;
  &lt;li&gt;High scalability O(logN)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
  &lt;li&gt;Slow work&lt;/li&gt;
  &lt;li&gt;Delays (new messages are not processed until all rounds are over)&lt;/li&gt;
  &lt;li&gt;Hard to debug&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h2&gt;

&lt;p&gt;Peer-to-peer networks are not a “silver bullet”. They have pros and cons. That’s why client-server approach is a widespread right now. P2P networks can be useful in some cases - e.g. in the blockchain networks.&lt;/p&gt;

&lt;p&gt;Although the Gossip protocol is quite simple and obvious, it has many applications in real systems. 
In the following posts, we will see in more detail how the Gossip protocol works on the example of Bitcoin and other blockchains.&lt;/p&gt;

&lt;p&gt;For those who want to understand the work of the Gossip protocol in more detail and theoretically - I recommend an &lt;strong&gt;&lt;a href=&quot;https://www.comp.nus.edu.sg/~ooiwt/papers/fanout-icdcs05-final.pdf&quot;&gt;interesting scientific work on this topic.&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content><author><name>Oleksandr Romanov</name></author><summary type="html">Photo by Federico Beccari on Unsplash</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://alexromanov.github.io/img/20220529/network.jpg" /><media:content medium="image" url="https://alexromanov.github.io/img/20220529/network.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Blockchain for Test Engineers: Distributed Systems</title><link href="https://alexromanov.github.io/2022/05/22/bchain-test-4-distributed-systems/" rel="alternate" type="text/html" title="Blockchain for Test Engineers: Distributed Systems" /><published>2022-05-22T06:00:00+00:00</published><updated>2022-05-22T06:00:00+00:00</updated><id>https://alexromanov.github.io/2022/05/22/bchain-test-4-distributed-systems</id><content type="html" xml:base="https://alexromanov.github.io/2022/05/22/bchain-test-4-distributed-systems/">&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/photos/gC_aoAjQl2Q?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditShareLink&quot;&gt;Shubham Dhage on Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the fourth blog post in the &lt;a href=&quot;https://alexromanov.github.io/2022/04/24/blockchain-testing-mindmap/&quot;&gt;&lt;strong&gt;“Blockchain for Test Engineers”&lt;/strong&gt;&lt;/a&gt; series.&lt;/p&gt;

&lt;p&gt;In the previous posts, we talked about the tiny little pieces of blockchain knowledge: &lt;a href=&quot;https://alexromanov.github.io/2022/05/01/bchain-testing-1-hashing/&quot;&gt;hashing&lt;/a&gt;, &lt;a href=&quot;https://alexromanov.github.io/2022/05/08/bchain-testing-2-encryption/&quot;&gt;encryption&lt;/a&gt; and &lt;a href=&quot;https://alexromanov.github.io/2022/05/15/bchain-testing-3-signatures/&quot;&gt;digital signatures&lt;/a&gt;. This time we will examine bits of the vast topic of &lt;strong&gt;distributed systems&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;why-would-i-need-to-know-about-distributed-systems---im-just-a-tester&quot;&gt;Why would I need to know about distributed systems - I’m just a tester?&lt;/h2&gt;
&lt;p&gt;If you are testing an application that is little more than a couple of simple scripts, there is a non-zero chance that you are developing (or using) distributed systems in one way or another.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Does your application have a &lt;strong&gt;database&lt;/strong&gt;? It may be distributed.&lt;/li&gt;
  &lt;li&gt;Do you have &lt;strong&gt;microservices&lt;/strong&gt; on the backend? It is also, in essence, a distributed system.
Do load balancers regulate the incoming traffic? Balancers can also be distributed.&lt;/li&gt;
  &lt;li&gt;Components exchange messages via &lt;strong&gt;messaging&lt;/strong&gt; (for example, Apache Kafka)? And that can be distributed too.
Do you host &lt;strong&gt;several data centers&lt;/strong&gt; in different parts of the world to give users faster answers? This is also a distributed system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220522/example.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In fact, &lt;strong&gt;almost any large modern application is a distributed system. And consists of several smaller systems.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In my opinion, test engineers who deal with distributed systems in one way or another should at least know these three things:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;how do these systems work? (easy level)&lt;/li&gt;
  &lt;li&gt;how can these systems fail? (medium level)&lt;/li&gt;
  &lt;li&gt;how can the risk of failure be reduced? (hard level)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also - almost each &lt;strong&gt;blockchain system is distributed and peer-to-peer&lt;/strong&gt; in a nutshell. So you need to know how distributed systems work and on which principles they are built.&lt;/p&gt;

&lt;h2 id=&quot;why-do-we-need-distributed-systems-at-all&quot;&gt;Why do we need distributed systems at all?&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Resiliency.&lt;/strong&gt; If all calculations are carried out on only one machine, then the failure of such a machine will mean that the entire system will be inaccessible to the user.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Performance.&lt;/strong&gt; Even the most powerful one, no single computer can handle simultaneous requests from millions and billions of users.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Handle significant computational problems.&lt;/strong&gt; Many tasks will be impossible or highly time-consuming to compute on a single machine.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;what-is-a-distributed-system&quot;&gt;What is a Distributed System?&lt;/h2&gt;
&lt;p&gt;In simple words, a &lt;strong&gt;distributed system&lt;/strong&gt; is a system that &lt;strong&gt;consists of many nodes&lt;/strong&gt; (for example, computers, processes, devices) that &lt;strong&gt;communicate over a network&lt;/strong&gt; and &lt;strong&gt;perform some form of a task together.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220522/distributed.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Leslie_Lamport&quot;&gt;Leslie Lamport&lt;/a&gt;, a renowned researcher and author of scientific papers, gave this description:
&lt;em&gt;”. . . a system in which the failure of a computer you didn’t even know existed can render your own computer unusable.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Distributed systems are a really vast topic. A lot of researchers dedicate their lives to learning distributed systems.&lt;/p&gt;

&lt;p&gt;As an engineer, you need to be aware of the following things about distributed systems:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;what are timing models (synchronous, asynchronous, or partially synchronous)&lt;/li&gt;
  &lt;li&gt;what is the type of communication between nodes&lt;/li&gt;
  &lt;li&gt;what are failure modes (the node can stop working in case of failure or recover automatically)&lt;/li&gt;
  &lt;li&gt;what are failure detectors in the system (how nodes can discover that something wrong happened to other nodes)&lt;/li&gt;
  &lt;li&gt;what are leader elections, quorums, and consensus protocols mean (RAFT, Paxos, Multi-Paxos, etc.)&lt;/li&gt;
  &lt;li&gt;how to calculate time in distributed systems (primarily if the nodes are geographically distributed around the world)&lt;/li&gt;
  &lt;li&gt;what are the standard whitepapers and principles in distributed systems (e.g., FLP Consensus)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;what-are-the-misconceptions-about-distributed-systems&quot;&gt;What are the misconceptions about distributed systems?&lt;/h2&gt;
&lt;p&gt;Developers who write code for distributed systems are far from ideal. Especially if they are new to the industry or have never dealt with massive systems. Such developers can form many false assumptions about distributed systems in their heads.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/L._Peter_Deutsch&quot;&gt;Peter Deutsch&lt;/a&gt; (and several other engineers) from Sun Microsystems back in the 90s formed a list of these assumptions. It can be found as “8 fallacies of distributed computing” on the Internet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Eight misconceptions about distributed systems:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;The network is reliable.&lt;/strong&gt; In reality, packets in the network can be lost; services can stop and endlessly wait for a response.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Network latency is zero.&lt;/strong&gt; There will always be network latency - at least, it’s limited by the speed of light. It is impossible to instantly transmit a packet over the network from one point on the Earth to another.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The bandwidth is infinite.&lt;/strong&gt; The bandwidth is limited, but it can also be different for different nodes.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The network is secure.&lt;/strong&gt; In fact, any messages sent over the network can be intercepted by attackers. Or hosts can be attacked or blocked.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The network topology does not change.&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;There is always one administrator on the network.&lt;/strong&gt; Nodes and subnets can be managed by many various companies with different security policies.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Transport costs are zero.&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The network is homogeneous.&lt;/strong&gt; In the real world, nodes on a network can be completely different, with different characteristics.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;distributed-systems-from-a-testing-point-of-view&quot;&gt;Distributed systems from a testing point of view&lt;/h2&gt;

&lt;p&gt;As distributed systems have many aspects, let’s take one of them as an example: &lt;strong&gt;communication.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By communication, we mean exchanging messages between two nodes (Node 1 and Node 2) or between the client and any node in the system.
The most straightforward and practical example is when a client makes a standard HTTP request to a server.&lt;/p&gt;

&lt;p&gt;What can happen in communication between two nodes?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220522/failures.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Node 1 sends a request and receives a response from Node 2.&lt;/li&gt;
  &lt;li&gt;Node 1 sends a request, and the request will not reach Node 2.&lt;/li&gt;
  &lt;li&gt;Node 1 sends a request, and Node 2 receives the request and tries to process it. During processing, Node 2 becomes unavailable for Node 1. (But under the hood, Node 2 can also make requests to other nodes!)&lt;/li&gt;
  &lt;li&gt;Node 1 sends a request to Node 2. Node 2 processes the request and returns a response, but Node 1 does not receive it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If Node 1 does not receive a response from Node 2, then it will not be able to understand what is causing the problem. It could be network problems and message loss, a Node 2 problem, or a dead link.&lt;/p&gt;

&lt;p&gt;So that Node 1 does not wait forever for a response, you can use the mechanism of &lt;strong&gt;waiting (Timeout)&lt;/strong&gt; for a response. Out of timeout - Node 1 generated a communication error.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But what should be the timeout?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you set the timeout too low, Node 1 may mistakenly think that Node 2 is unavailable. On the other hand, if the timeout is too long, the waiting time can significantly impact system performance.&lt;/p&gt;

&lt;p&gt;You can use the &lt;strong&gt;ping&lt;/strong&gt; and &lt;strong&gt;heartbeat&lt;/strong&gt; mechanisms as an alternative to timeouts.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Ping.&lt;/strong&gt; Node 1 can ping Node 2 from time to time and check if the node is alive. Even if, at some point, the node does not respond, Node 1 can continue to send such requests in the hope that Node 2 will be available sooner or later.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Heartbeat.&lt;/strong&gt; Node 2 can send particular messages to all nodes it communicates. Thus, it notifies the network that it is up and running. If Node 1 does not receive heartbeat messages from Node 2, it marks that node as unreachable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both mechanisms are used in distributed systems - e.g., for communication and synchronizing microservices on the backend.&lt;/p&gt;

&lt;p&gt;It is only one example of how we can think about distributed systems and try to develop testing scenarios for them.&lt;/p&gt;

&lt;h2 id=&quot;learning-about-distributed-systems&quot;&gt;Learning about distributed systems&lt;/h2&gt;

&lt;p&gt;It is up to you to dive into distributed systems in-depth or not. Suppose you test some DeFi protocols or applications that only use a specific blockchain (Ethereum or Cardano). In that case, you need to concentrate on these protocols’ technical and business aspects first. Learning about internals adds more benefits later.&lt;/p&gt;

&lt;p&gt;But if you are a part of a core development team or building a distributed system (or blockchain) from scratch - you must know the theoretical basis.&lt;/p&gt;

&lt;p&gt;If you are interested in distributed systems - I want to share a few resources on where to start.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Simple explanations can be found in the &lt;a href=&quot;https://youtube.com/playlist?list=PLOE1GTZ5ouRPbpTnrZ3Wqjamfwn_Q5Y9A&quot;&gt;introductory course created by Chris Colohan&lt;/a&gt;. It is a good starting point for newcomers.&lt;/li&gt;
  &lt;li&gt;If you want to read a single book - it is &lt;a href=&quot;(https://www.amazon.com/Designing-Data-Intensive-Applications-Reliable-Maintainable/dp/1449373321)&quot;&gt;“Designing Data-Intensive Applications”&lt;/a&gt; by Martin Kleppmann. I even made a review post about this book &lt;a href=&quot;https://alexromanov.github.io/2021/07/26/ddia-for-testers/&quot;&gt;last year.&lt;/a&gt;. The book can be hard to read, but it is full of helpful information.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If you prefer to watch videos - here is &lt;a href=&quot;https://youtube.com/playlist?list=PLeKd45zvjcDFUEv_ohr_HdUFe97RItdiB&quot;&gt;a course on distributed systems at the University of Cambridge taught by Martin Kleppmann&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;What can you learn from the course?&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;what distributed systems are and how nodes can communicate with each other&lt;/li&gt;
      &lt;li&gt;canonical theoretical tasks from two generals to Byzantine ones.&lt;/li&gt;
      &lt;li&gt;time and how to work with it in large systems: physical and logical clocks, clock synchronization, and cause-and-effect relationship of events on different nodes&lt;/li&gt;
      &lt;li&gt;the concept of replication and quorums, as well as message broadcasting algorithms&lt;/li&gt;
      &lt;li&gt;consensus algorithms - from the simplest to even simpler (RAFT)&lt;/li&gt;
      &lt;li&gt;how Google Spanner works and different tools for collaboration between users&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;For more in-depth explanations of consensus protocols you can watch an academic &lt;a href=&quot;(https://youtube.com/playlist?list=PLNPUF5QyWU8PydLG2cIJrCvnn5I_exhYx)&quot;&gt;course from Lindsey Kooper&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h2&gt;

&lt;p&gt;Distributed systems are a vast but really fascinating topic to learn. As our modern systems are getting bigger and more complex, the knowledge about distributed computing and consensus algorithms can significantly benefit you.&lt;/p&gt;

&lt;p&gt;It is a must-have knowledge if you work with blockchain systems (at least from the theoretical part). Otherwise, you will always test your app against the blockchain as a &lt;strong&gt;black-box&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/20220522/blackbox.png&quot; alt=&quot;Project Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Such testing is not a bad thing at all - but you may miss a lot of important internal issues by concentrating only on the surface.&lt;/p&gt;</content><author><name>Oleksandr Romanov</name></author><summary type="html">Photo by Shubham Dhage on Unsplash</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://alexromanov.github.io/img/20220522/distsys.jpg" /><media:content medium="image" url="https://alexromanov.github.io/img/20220522/distsys.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>