<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Ajdin Mustafić</title>
    <description>The latest articles on Forem by Ajdin Mustafić (@ajdinmust).</description>
    <link>https://forem.com/ajdinmust</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F345783%2F0ea9523c-cefb-4cd1-a189-b4ffbde6713d.jpg</url>
      <title>Forem: Ajdin Mustafić</title>
      <link>https://forem.com/ajdinmust</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ajdinmust"/>
    <language>en</language>
    <item>
      <title>Reload the window if an element is not found —  Cypress Automation</title>
      <dc:creator>Ajdin Mustafić</dc:creator>
      <pubDate>Wed, 21 Jun 2023 12:06:11 +0000</pubDate>
      <link>https://forem.com/ajdinmust/reload-the-window-if-an-element-is-not-found-cypress-automation-2l42</link>
      <guid>https://forem.com/ajdinmust/reload-the-window-if-an-element-is-not-found-cypress-automation-2l42</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3eVm3iU1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A7zFhukR87MYDz-Y7oG2NHQ.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3eVm3iU1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A7zFhukR87MYDz-Y7oG2NHQ.jpeg" alt="" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cypress is a powerful test automation tool that executes very fast, in my experience, sometimes even too fast… I used a recursive function to reload the window if an element was not propagated on the frontend on time.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test case:&lt;/strong&gt; Remove the tag from a mention.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Test case background:&lt;/em&gt; &lt;a href="https://www.determ.com/"&gt;&lt;em&gt;Determ&lt;/em&gt;&lt;/a&gt; &lt;em&gt;app is a media monitoring tool that tracks brand mentions from all over the internet. One of its features is that a user, for easier sorting of their mentions, can create and add tags to each of the mentions, and remove them of course.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In my Cypress automated test, to remove a tag from a mention, the tag needs to be created first, so the test creates a tag on the backend before validating that it can be removed on the frontend. However, sometimes it happens that the tag gets created on the backend and does not get propagated on the frontend soon enough, i.e. it does not appear before the Cypress visits the feed page. If that happens when manually visiting the page, which is hard to happen — only in the case of a heavy load on a system, you would need to reload the page and the tag would show up. And that is exactly what I needed to implement in my automated test.&lt;/p&gt;

&lt;h4&gt;
  
  
  Problems and Solutions
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;Issue:&lt;/em&gt; Sometimes, but not every time, Cypress visits the page too soon before the “tag” element is propagated on the frontend.
&lt;em&gt;Solution:&lt;/em&gt; Use &lt;code&gt;cy.reload()&lt;/code&gt; to reload the window.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Issue:&lt;/em&gt; When Cypress does not find an element that you put in the test, it fails with an error that element does not exist.
&lt;em&gt;Solution:&lt;/em&gt; Use a recursive function* that reloads the window if the given element is not found.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Issue:&lt;/em&gt; Edge case alert — if somehow happens that the tag does not get created on the backend at all, the function will end up in an infinite loop because no matter how many times it reloads the element won't be found.
&lt;em&gt;Solution:&lt;/em&gt; Add a retry increment to each call of the function and add a rule for maximum retries — if the element did not show up after the first or second window reload, it probably won’t at all so throw an error.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Positive outcome:&lt;/em&gt; If the tag element is loaded on time or loaded after a window reload, validate that it is visible and continue with the test.&lt;/li&gt;
&lt;/ol&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Function explanation:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;First Cypress gets an element of one mention.&lt;/li&gt;
&lt;li&gt;On that element/mention checks if there is text with the added tag name&lt;/li&gt;
&lt;li&gt;First if condition — if the text on the mention does not include added tag name -&amp;gt; reload the window -&amp;gt; call the function again and increment retries by one.&lt;/li&gt;
&lt;li&gt;Second if condition — if max retries is equal to retries -&amp;gt; throw an error and fail the test.&lt;/li&gt;
&lt;li&gt;If all conditions pass — Cypress checks that the tag on the mention element contains the text of the created tag -&amp;gt; the function finishes -&amp;gt; the test continues with execution&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Using recursion instead of loop commands (like while)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using JavaScript loop commands like while can have unexpected effects because Cypress commands are asynchronous and get queued for execution at a later time. And in my case, if I had used the loop instead of recursion, the Cypress would just pile up “cy.get(‘mention-tags’)” commands to the test chain, without executing any. Then the chain of commands would keep growing but never execute — since the test function would never finish running. The while loop never allows Cypress to start executing even the very first &lt;code&gt;cy.get(…)&lt;/code&gt; command.&lt;/p&gt;

&lt;h4&gt;
  
  
  Final thoughts
&lt;/h4&gt;

&lt;p&gt;By implementing a recursive function and utilizing window reloading in Cypress test automation, we have effectively addressed the issue of elements not being propagated on the front end in time. This solution ensures more reliable and stable test execution, enhancing the effectiveness of our Cypress automated tests.&lt;/p&gt;

&lt;p&gt;Also, there are many useful ways to utilize recursion with Cypress. For example, if you need to find a user in a list that has pagination, a function can check if the user’s name is on the first page, if not, click on the next page and call the function again, if the next page can’t be clicked, throw an error that the user is not to be found in the list.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;*A recursive function is a type of function that calls itself until your program achieves the desired result.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Find out more:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.cypress.io/guides/core-concepts/introduction-to-cypress#Avoid-loops"&gt;https://docs.cypress.io/guides/core-concepts/introduction-to-cypress#Avoid-loops&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cypress.io/guides/core-concepts/introduction-to-cypress#Mixing-Async-and-Sync-code"&gt;https://docs.cypress.io/guides/core-concepts/introduction-to-cypress#Mixing-Async-and-Sync-code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.freecodecamp.org/news/what-is-recursion-in-javascript/"&gt;https://www.freecodecamp.org/news/what-is-recursion-in-javascript/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://help.determ.com/en/articles/6600022-mention-tagging"&gt;https://help.determ.com/en/articles/6600022-mention-tagging&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cypress</category>
      <category>automationtesting</category>
      <category>recursion</category>
      <category>javascript</category>
    </item>
    <item>
      <title>BDD: Automation Testing with Cucumber</title>
      <dc:creator>Ajdin Mustafić</dc:creator>
      <pubDate>Thu, 06 Apr 2023 07:00:00 +0000</pubDate>
      <link>https://forem.com/ajdinmust/bdd-automation-testing-with-cucumber-2l48</link>
      <guid>https://forem.com/ajdinmust/bdd-automation-testing-with-cucumber-2l48</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frb8zok6n5ysjlz2ovu42.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frb8zok6n5ysjlz2ovu42.jpeg" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Behavior-Driven Development is an Agile software development process that promotes collaboration between developers, software testers (QA) and the non-technical, business side in a software development process.
&lt;/h3&gt;

&lt;p&gt;Outcome of their meetings are structured scenarios which act as requirements for product owners, acceptance criteria for developers, description for stakeholders, test cases and automation scripts for testers.&lt;/p&gt;

&lt;p&gt;Our focus in this blog will be on test cases and automation scripts for testers. However, if you would like to read more about BDD itself, you can check out &lt;a href="https://www.bornfight.com/blog/behavior-driven-development-how-to-find-bugs-before-coding-starts/" rel="noopener noreferrer"&gt;my previous blog&lt;/a&gt; which explains the BDD processes more thoroughly.&lt;/p&gt;

&lt;h4&gt;
  
  
  Cucumber and Gherkin
&lt;/h4&gt;

&lt;p&gt;Behavior-Driven Development is supported by a software tool called &lt;strong&gt;Cucumber&lt;/strong&gt;. It is used to write acceptance tests for the software, and to run the tests in BDD style.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcg4mi92j2x4t2jkpuwfo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcg4mi92j2x4t2jkpuwfo.png" width="800" height="424"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Source: miro.medium.com&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Cucumber uses a plain language parser called &lt;strong&gt;Gherkin&lt;/strong&gt; , which is of great importance to the Cucumber BDD approach. Thanks to Gherkin, we can write expected software behaviors specified in a logical and structured language that everyone on the project can understand — from developers to the customers.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Feature File&lt;/strong&gt; is a starting point of the Cucumber test because it serves as an automation test script and the living documentation. Feature files can contain scenarios, scenario steps, scenario outline, tags and examples. All the feature files end with the “.feature” extension (Login.feature).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 1:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Feature: GoogleSearching 
In order to find company information 
As a user
I need to be able to search Google 

Scenario:Google Searching 
**Given** a web browser is at "Google" homepage
**When** the user enters "Bornfight" into the search bar
**Then** links related to "Bornfight" are shown on the result page

Scenario: Video search
**Given** Google search results for "Bornfight" are shown
**When** the user clicks on the "Videos" link at the top of the result page
**Then** videos related to "Bornfight" are shown on the result page
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Feature&lt;/strong&gt; gives information about a standalone unit or functionality of a project. It may also contain &lt;strong&gt;Description&lt;/strong&gt; of the feature (In order to…As a user…I need to be able…).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt; represents a particular functionality of a feature which is under test. One feature file can contain more than one scenario, but one scenario can have only one behaviour. If you felt a need to use &lt;strong&gt;When&lt;/strong&gt; and &lt;strong&gt;Then&lt;/strong&gt; more than once in your scenario, it means that there are two behaviours and there is a space for two separate scenarios. Referring to the Example 1, this would be an incorrect way to write the scenario.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 2:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Scenario: Google Video search shows videos
**Given** a web browser is at "Google" homepage
**When** the user enters "Bornfight" into the search bar
**Then** links related to "Bornfight" are shown on the result page
**When** the user clicks on the "Videos" link at the top of the result page
**Then** videos related to "Bornfight" are shown on the result page
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You probably noticed here that &lt;strong&gt;When&lt;/strong&gt; and &lt;strong&gt;Then&lt;/strong&gt; are repeated, and there are two different actions/behaviours meaning that you should write two different scenarios. By seeing the scenario, any of the stakeholders should be able to understand what is being tested. Scenario is always followed by &lt;strong&gt;scenario steps&lt;/strong&gt; in the Given-When-Then format.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Given — Prediction — Context&lt;br&gt;&lt;br&gt;
When — Action — Event&lt;br&gt;&lt;br&gt;
Then — Outcomes — Result&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is a Gherkin format where the steps must be written strictly in this order and none of them should be repeated. If you want to add more than one line in each step, you can use &lt;strong&gt;And&lt;/strong&gt; or &lt;strong&gt;But&lt;/strong&gt;. Both of them are logically the same, except for the fact that But is used in a negative way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 3:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**Given** a web browser is at "Google" homepage
**When** the user enters "Apple Inc." into the search bar
**And** the user search for images
**Then** the images related to "Apple Inc." should be shown
**But** the images related to fruit Apple should not be shown
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Scenario outline&lt;/strong&gt; , together with &lt;strong&gt;Examples&lt;/strong&gt; , is used when you perform the same test with different data sets. In this example, we checked if all the team members are presented on the company’s web page.&lt;/p&gt;

&lt;p&gt;Example 4:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Feature: CheckBornfightTeam
In order to check if Bornfight web is updated with the new team members 
As a Bornfight web visitor I need to see new team member's name in the list 

**Scenario Outline:** Check Bornfight Team

**Given** I am on page "/team"
**When** I look up for the team member
**Then** I should see "&amp;lt;name&amp;gt;" name

**Examples:** 
| name | 
| Kristijan Bujanović | 
| Marko Kruljac | 
| Josip Trbuščić | 
| Ajdin Mustafić |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Tags
&lt;/h4&gt;

&lt;p&gt;Scenarios and features can contain tags and they are marked with @. With tags, we can group scenarios and features in an order that we want to run them. For example, we can mark important scenarios with @important or scenarios for smoke testing with &lt;a class="mentioned-user" href="https://dev.to/smoke"&gt;@smoke&lt;/a&gt;… &lt;strong&gt;Tags are very useful for arranging scenarios when you have 10–20 of them in one feature.&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Steps definitions
&lt;/h4&gt;

&lt;p&gt;Defining all the elements in the feature file doesn’t mean that the tests are ready to be executed. We have defined test scenarios, but the Cucumber doesn’t really know which piece of code should be executed for each line of the scenario. For that reason, we need a steps definition file, &lt;strong&gt;a glue between the scenario and the application&lt;/strong&gt;. In the steps definition file, we have a mapping between each step of the scenario and the code of function to be executed.&lt;/p&gt;

&lt;p&gt;In our examples, we use &lt;strong&gt;PHP&lt;/strong&gt; with &lt;strong&gt;Codeception&lt;/strong&gt; and &lt;strong&gt;Selenium&lt;/strong&gt; to write tests and run them in the browser. Here you can see how each line in our scenario looks as a code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Scenario: Google Searching
 **Given** a web browser is at "Google" homepage
 public function aWebBrowserIsAtHomepage($arg1)
 {

 $this-&amp;gt;amOnPage('/'); 
 }

**When** the user enters "Bornfight" into the search bar
 public function theUserEntersIntoTheSearchBar($arg1)
 {
 $this-&amp;gt;pressKey("//input[@name='q']", $arg1, \Facebook\WebDriver\WebDriverKeys::ENTER);
 }

**Then** links related to "Bornfight" are shown on the result page
 public function linksRelatedToAreShownOnTheResultPage($arg1)
 {
 $this-&amp;gt;waitForText($arg1);
 $this-&amp;gt;see($arg1);

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;This is one basic example of how the scenario steps and steps definitions are connected. However, depending on the requirements of the test and the complexity of the tested feature, writing step definitions can get more complicated. While on the other hand, writing scenario steps should remain basic and easy to understand.&lt;/p&gt;

&lt;p&gt;As you can see, the scenarios written in Gherkin are a documentation that’s structured and very easy to understand. A documentation which you can use to run acceptance tests. Also, they are easy to write and edit, therefore we can address them as living documentation. In short, writing feature scenarios in the BDD approach is of great value when it comes to testing, test coverage, documenting features, editing documentation and confirming that the feature works as it was intended to.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you want to learn more about BDD, check out some of these articles:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.softwaretestinghelp.com/cucumber-bdd-tool-selenium-tutorial-30/" rel="noopener noreferrer"&gt;Automation Testing Using Cucumber Tool And Selenium — Selenium Tutorial #30&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.toolsqa.com/cucumber/cucumber-jvm-feature-file/" rel="noopener noreferrer"&gt;Cucumber Feature File&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codeception.com/docs/07-BDD" rel="noopener noreferrer"&gt;BEHAVIOR DRIVEN DEVELOPMENT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tutorialspoint.com/cucumber/cucumber_features.htm" rel="noopener noreferrer"&gt;Cucumber — Features&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>todayilearned</category>
      <category>datascience</category>
      <category>analytics</category>
    </item>
    <item>
      <title>Cypress 10: Using Multiple Config Files</title>
      <dc:creator>Ajdin Mustafić</dc:creator>
      <pubDate>Mon, 06 Mar 2023 00:00:00 +0000</pubDate>
      <link>https://forem.com/ajdinmust/cypress-10-using-multiple-config-files-3k7</link>
      <guid>https://forem.com/ajdinmust/cypress-10-using-multiple-config-files-3k7</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--owUzJpj4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A2YPshgVie4Ot2FRMwt1ygw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--owUzJpj4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A2YPshgVie4Ot2FRMwt1ygw.png" alt="" width="880" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Running the same tests for different user types using multiple config files
&lt;/h3&gt;

&lt;p&gt;In the Mediatoolkit app, each user organization can have a different pricing plan. Different pricing plans mean that some users can use some features while others can’t. You can check out the detailed feature description for each plan here — &lt;a href="https://www.mediatoolkit.com/pricing"&gt;pricing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Recently we changed our pricing plan structure. This means we needed to check every feature for users in each pricing plan. This included running all the same tests and test cases for users in each pricing plan.&lt;/p&gt;

&lt;h3&gt;
  
  
  How did the multiple config files help?
&lt;/h3&gt;

&lt;p&gt;In our Cypress automated tests, we use the access token, organization id, and query id parameters for logging in and visiting pages to which the logged-in user has access. These parameters are different for each user. If you want to run a test with a different user, you need to change all the parameters or write a different test for each user. We didn’t want to change these every time inside the test code. So, we made config files for each user where we can store their access token, organization id, and query id. This way, when we wanted to run a set of tests for a user with the “Agency” price plan, we’d run the config file we made for that particular user. Nevertheless, in the config file, you can exclude the tests that are unrelated to that user and don’t want to run at all.&lt;/p&gt;

&lt;p&gt;By running these tests for different users on different price plans, we validate if a particular user should or shouldn’t have access to the features available in their pricing plan. That way, you can check all the features for one user in a few minutes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QxeVCWRj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/268/0%2A8qp1Z7HJTIa-H8T8" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QxeVCWRj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/268/0%2A8qp1Z7HJTIa-H8T8" alt="" width="268" height="139"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating and Running New Config Files
&lt;/h3&gt;

&lt;p&gt;The easiest and safest way to create a new config file is to duplicate the existing Cypress config file (“cypress.config.js). Then, change its name to something new, for example, cypress.development.config.js, and configure it as you wish.&lt;/p&gt;

&lt;p&gt;You can run your tests with different config files by running your standard command with added “-config-file” flag and the path to the config file. For example, “cypress run -config-file configs/cypress.individualplan.config.js”&lt;/p&gt;

&lt;p&gt;Another way, and a much better way, is by setting a reference in your package.json file with a unique command:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Other use cases
&lt;/h3&gt;

&lt;p&gt;Another use case for our app is running the same tests for different user roles inside one organization. For us, inside one organization, you can be Admin, Analyst, Editor, or just a Viewer. However, much broader use cases are running your tests in different environments so you can have development, staging, and production config files. Or, for example, you can have a config file with a different resolution set up if you want to validate your web application in mobile view.&lt;/p&gt;

&lt;p&gt;Feel free to &lt;a href="https://www.linkedin.com/in/ajdin-must/"&gt;contact me&lt;/a&gt; if you have any questions or if you know a better way to approach these cases.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Conditional Waiting in Cypress</title>
      <dc:creator>Ajdin Mustafić</dc:creator>
      <pubDate>Wed, 01 Mar 2023 11:00:00 +0000</pubDate>
      <link>https://forem.com/ajdinmust/conditional-waiting-in-cypress-3gca</link>
      <guid>https://forem.com/ajdinmust/conditional-waiting-in-cypress-3gca</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--owUzJpj4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A2YPshgVie4Ot2FRMwt1ygw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--owUzJpj4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A2YPshgVie4Ot2FRMwt1ygw.png" alt="" width="880" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;By using a recursive function, you can repeatedly wait for the request until you get the desired response&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Test Case
&lt;/h4&gt;

&lt;p&gt;Our test case involves an existing user (permanent user) who invites a new user via email. The new user receives a registration link and registers for the &lt;a href="http://determ.com"&gt;Determ&lt;/a&gt; application. After the new user has been registered and has access to the app, we need to delete them to “clean up” after the test. However, we don’t want to delete the existing user, so we need to check the user ID before deleting the user.&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;To delete the newly created user, we need to intercept and wait for a specific API request that contains the user’s access token. However, the same request is also sent for the existing user, and we don’t want to delete them. The only difference between the users is their user ID, which we can only get from the response of the API request.&lt;/p&gt;

&lt;p&gt;To solve this problem, we can use a recursive function that waits for the API request and checks the user ID. If the user ID is the same as the ID of the existing user, the function calls itself again. If the user ID is not the same, we save the access token and use it to delete the user later.&lt;/p&gt;

&lt;p&gt;Here’s the code for the recursive function:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Then inside your test just call the function:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k4NV0YDm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/688/1%2A1-t3e18tmAVlIiCWfXJunA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k4NV0YDm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/688/1%2A1-t3e18tmAVlIiCWfXJunA.png" alt="" width="688" height="100"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Conditional cy.wait()&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;By checking the user ID in the response, we can make sure we only delete the correct user. The recursive function approach can be useful when you need to wait for a specific API request and process its response conditionally. And by using a recursive function, you can repeatedly wait for the request until you get the desired response.&lt;/p&gt;

&lt;p&gt;If you have a similar problem or need help implementing this solution, feel free to leave a comment.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to Read Emails in Cypress</title>
      <dc:creator>Ajdin Mustafić</dc:creator>
      <pubDate>Wed, 22 Feb 2023 09:07:33 +0000</pubDate>
      <link>https://forem.com/ajdinmust/how-to-read-emails-in-cypress-20ja</link>
      <guid>https://forem.com/ajdinmust/how-to-read-emails-in-cypress-20ja</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3FHUs7fF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ANftUAcNZWiY-J2zHFuX2mw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3FHUs7fF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ANftUAcNZWiY-J2zHFuX2mw.png" alt="" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  E2E Automated Sign up Test
&lt;/h3&gt;

&lt;p&gt;Some people overlook the importance of testing the sign up flow. They might think that’s the first thing that they have developed, tested it over and over while developing other features, and it probably should be working.&lt;/p&gt;

&lt;p&gt;However, it can happen that the sign up suddenly starts failing for various reasons. If it does fail, you would want to know it as soon as possible. The later you realize the failure, the more potential new users it can drive off. That is the reason we have an automated test for the sign up/registration flow which gives us a report if something is off, on a daily basis.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U0Z7d82h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/683/0%2AVdGZWTuEPqZMpmKQ.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U0Z7d82h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/683/0%2AVdGZWTuEPqZMpmKQ.jpeg" alt="" width="683" height="1024"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Photo by Markus Spiske on Unsplash&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Test Flow
&lt;/h3&gt;

&lt;p&gt;For this example, we’ll be going through Mediatoolkit’s sign up and registration page. Here’s how the test flow goes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User enters their email on the Mediatoolkit sign up page (&lt;a href="https://www.mediatoolkit.com/signup"&gt;https://www.mediatoolkit.com/signup&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;User opens a link received via email&lt;/li&gt;
&lt;li&gt;User is redirected to the registration form&lt;/li&gt;
&lt;li&gt;User fills out the registration form&lt;/li&gt;
&lt;li&gt;User finishes registration and gets logged in the app&lt;/li&gt;
&lt;li&gt;Delete the user (clean up after the test)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Apart from the standard registration flow, I have added the “delete user” step as well. So, after we confirm that the user is registered, we delete that user using API. That way, we get to the initial state which was before the test started. This ensures that the test does not make a lot of junk in the database and is able to run over and over as many times as we want.&lt;/p&gt;
&lt;h3&gt;
  
  
  Test Goal
&lt;/h3&gt;

&lt;p&gt;Our test asserts that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A user can enter an email address on the sign up page&lt;/li&gt;
&lt;li&gt;A user gets an email from Mediatoolkit&lt;/li&gt;
&lt;li&gt;The email contains a valid confirmation link&lt;/li&gt;
&lt;li&gt;A user can fill out the form and finish the registration on the link from the email&lt;/li&gt;
&lt;li&gt;A user gets logged in after finishing the registration&lt;/li&gt;
&lt;li&gt;A user gets deleted after all the previous requirements are successfully validated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since our test aims to validate that the email is being both sent and received, i.e. the same flow as the user would go through, I wanted to make it as similar as possible to the real user flow, so mocking this part was not an option for me.&lt;/p&gt;
&lt;h3&gt;
  
  
  How do I read my emails in Cypress?
&lt;/h3&gt;

&lt;p&gt;As you could see in the previous sections, in order to finish the registration, you need to visit the link that you received in the welcome email. But to do so, you need to access your email inbox, preferably via API. Luckily, I found a &lt;a href="https://levz0r.medium.com/how-to-poll-a-gmail-inbox-in-cypress-io-a4286cfdb888"&gt;blog&lt;/a&gt; about the Gmail-tester library by Lev Gelfenbuim which made this test implementation very smooth.&lt;/p&gt;

&lt;p&gt;Basically, what you need to do is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install the gmail-tester (&lt;em&gt;npm install — save-dev gmail-tester)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Save the Google Cloud Platform OAuth2 Authentication file named credentials.json inside an accessible directory&lt;/li&gt;
&lt;li&gt;In terminal, run the following command: &lt;em&gt;node /gmail-tester/init.js   &lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The detailed instructions on how to install and configure the gmail-tester, and your Google account, you can find on the gmail-tester github &lt;a href="https://github.com/levz0r/gmail-tester/blob/master/README.md#how-to-get-credentialsjson"&gt;readme&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Usage in the test
&lt;/h3&gt;

&lt;p&gt;In my cypress-config.js file I have:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;And inside of the “module.exports = defineConfig”,&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;As you may have seen in the previously mentioned blog, this piece of code would be in the “cypress/plugins/index.js”, but since I am using Cypress 10 now, it goes to the cypress-config.js file. Also, the code did not work for me until I added “subject:”, “from:”, “to:” in front of “subject”, “from”, and “to”, which is also different in the blog.&lt;/p&gt;

&lt;p&gt;Inside of the test file itself, you should have something like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;This task checks if there is an email existing in our inbox with the given parameters. Then you can console log the found email. The “html”, in my case, contains the html of the email that we have found in our Gmail inbox. Now, from that html you can take out the confirmation URL or any other information that you need.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xDD39F13--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/355/0%2A-lUfryoa9VKiM9zS" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xDD39F13--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/355/0%2A-lUfryoa9VKiM9zS" alt="" width="355" height="96"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Email found assertion&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;Relying on external sources in your test is usually not a good idea. However, if you would like to confirm exactly the same flow as your user would go through, you can try using Gmail-tester which makes it very easy to access an email in your Gmail inbox.&lt;/p&gt;

&lt;p&gt;Make sure you visit Gmail-tester &lt;a href="https://github.com/levz0r/gmail-tester"&gt;Github&lt;/a&gt; repository for more information and the latest updates.&lt;/p&gt;

&lt;p&gt;Feel free to &lt;a href="https://www.linkedin.com/in/ajdin-must/"&gt;contact me&lt;/a&gt; if you have any questions regarding the implementation.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Phone Number Normalisation</title>
      <dc:creator>Ajdin Mustafić</dc:creator>
      <pubDate>Mon, 28 Mar 2022 13:16:42 +0000</pubDate>
      <link>https://forem.com/bornfightcompany/phone-number-normalisation-4gpi</link>
      <guid>https://forem.com/bornfightcompany/phone-number-normalisation-4gpi</guid>
      <description>&lt;p&gt;The phone number normalisation is used to translate a phone number into a standard form.&lt;/p&gt;

&lt;p&gt;For example, there is E.164 international standard which defines format as "[+] [country code] [subscriber number including area code] and can have a maximum of fifteen digits". However, we rarely save numbers, especially domestic ones, in this exact format. &lt;/p&gt;

&lt;p&gt;This can be a huge problem if you wanted to allow your users to import their mobile phone contacts into your application. The users can have the phone number, in their phone contacts, entered with or without country code, or can enter country codes like 00385 or +385, etc. So if you didn't have the phone number normalisation, these two numbers 00385991234567 and +385991234567 would be imported as two different phone numbers for the same contact even though when calling, they are the same, just written in different format standards.&lt;/p&gt;

&lt;p&gt;We have a similar challenge on one of our projects, so our first step was to research, what should be covered and what others cover when they do the phone number normalisation. &lt;/p&gt;

&lt;p&gt;One of my outputs were the test cases that are covered by Whatsapp:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;I can't contact a foreign mobile number without a country code&lt;/strong&gt; - &lt;em&gt;For example, if your phone number is from Croatia and you saved a contact with a mobile phone number from Austria, without the country code, Whatsapp will not recognize it as existing.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I can contact domestic mobile number without country code&lt;/strong&gt; - &lt;em&gt;For example, if your phone number is from Croatia and you saved a contact with a mobile phone number from Croatia, without the country code, Whatsapp will recognize it as it is (existing).&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I can contact a foreign mobile number with "00" country code&lt;/strong&gt; - &lt;em&gt;For example, if your phone number is from Croatia and you saved a contact with a mobile phone number from Austria, with the 0043 country code standard, Whatsapp will recognize it as existing.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I can contact a foreign mobile number with a "+" country code&lt;/strong&gt; - &lt;em&gt;For example, if your phone number is from Croatia and you saved a contact with a mobile phone number from Austria, with the +43 country code standard, Whatsapp will recognize it.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I can contact a foreign mobile number with "+" country code and 0 before the mobile prefix&lt;/strong&gt; - &lt;em&gt;For example, save the foreign phone number in your contacts with "+" country code and zero before the mobile operator prefix (+385 &lt;strong&gt;0&lt;/strong&gt; 99 1234567). Whatsapp will recognize and normalise the number to +385 99 1234567.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I can't contact a foreign mobile number with "00" country code and 0 before mobile prefix&lt;/strong&gt; - &lt;em&gt;For example, save the foreign phone number in your contacts with "00385" country code and zero before mobile prefix (+385 &lt;strong&gt;0&lt;/strong&gt; 99 1234567). Whatsapp will not recognize the number as the same as +385991234567.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I can't contact domestic mobile number with "00" country code and 0 before mobile prefix&lt;/strong&gt; - &lt;em&gt;For example, save the domestic phone number in your contacts with "00385" country code and zero before mobile prefix (+385 &lt;strong&gt;0&lt;/strong&gt; 99 1234567). Whatsapp will not recognize the number as the same as +385991234567.&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Handling phone numbers, especially without normalisation can create a real mess in your application because many users in different countries use different phone number standards to create their contacts.&lt;/p&gt;

&lt;p&gt;Feel free to share your experience and your test case examples in the comments section.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>testing</category>
      <category>qualityassurance</category>
      <category>engineeringmonday</category>
    </item>
    <item>
      <title>Page Object Pattern + Reusable Functions in Cypress</title>
      <dc:creator>Ajdin Mustafić</dc:creator>
      <pubDate>Mon, 25 Oct 2021 14:49:33 +0000</pubDate>
      <link>https://forem.com/bornfightcompany/page-object-pattern-reusable-functions-in-cypress-35jj</link>
      <guid>https://forem.com/bornfightcompany/page-object-pattern-reusable-functions-in-cypress-35jj</guid>
      <description>&lt;h4&gt;
  
  
  If you have ever wished to have more structured, reusable, and readable automated tests, you should have started with the Page Object Pattern.
&lt;/h4&gt;

&lt;p&gt;&lt;b&gt;&lt;br&gt;
&lt;b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h5&gt;
  
  
  Page Object Pattern
&lt;/h5&gt;

&lt;p&gt;Page Object Pattern is basically removing all the page information from your actual test and grouping them together considering their location on your web page. For example, you can take all the selectors that you have on the homepage of your web and put them in one class, give them more meaningful names and then call them in any of your tests ...&lt;/p&gt;

&lt;p&gt;Imagine your homepage went through a design and development modification that impacted your selectors to change, you would need to go through all of your tests and change the same selector in all the places. However, with the page object pattern, you change the selector only in one place - in the class that you have created for the homepage selectors. There, you saved yourself a lot of time and made sure that there won't be some forgotten, unchanged, and obsolete selectors in one of your tests.&lt;/p&gt;
&lt;h4&gt;
  
  
  Adding More of Reusability
&lt;/h4&gt;

&lt;p&gt;Nevertheless, you can make your tests even more structured, reusable, understandable, and easier to maintain, by adding custom commands and reusable functions to them. The same way I made a class for homepage selectors I also made a class for all the functions from the homepage, that are used all over the different tests. For example, if I had 5 different tests/test cases where a user fills out the same form, I wouldn't be needed to copy/paste Cypress code to every each of the tests but I'd reuse the already written functions.&lt;/p&gt;

&lt;p&gt;Example how my Cypress test would look like with the page object pattern and reusable functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe("Fill out user satisfaction form", function () {

    it("Check if the user can fill out the form", function () {
        cy.visitFormsPage();
        cy.userAcceptsTerms();
        cy.userFillsOutsTheForm();
        cy.formFilledOutCorrectlyAssert();
    });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;b&gt;&lt;br&gt;
&lt;b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  All together now
&lt;/h5&gt;

&lt;p&gt;Combining page object pattern and reusable functions gave me a whole new perspective of the tests. Not only are they easier to use and maintain, but they also look very neat and easier to understand for my other colleagues, even non-technical members of the team. In the beginning, you need to spend a bit more time on the setup but later on, you will see that the effort is paid off.&lt;/p&gt;

&lt;p&gt;Feel free to share with me some of your "reusability" secrets.&lt;/p&gt;

</description>
      <category>engineeringmonday</category>
      <category>cypress</category>
      <category>testing</category>
      <category>testautomation</category>
    </item>
    <item>
      <title>A Whole Project Team Exploratory Testing Sessions</title>
      <dc:creator>Ajdin Mustafić</dc:creator>
      <pubDate>Mon, 24 May 2021 12:14:53 +0000</pubDate>
      <link>https://forem.com/bornfightcompany/a-whole-project-team-exploratory-testing-sessions-2kmj</link>
      <guid>https://forem.com/bornfightcompany/a-whole-project-team-exploratory-testing-sessions-2kmj</guid>
      <description>&lt;p&gt;I love working on challenging projects — they make me think more and I always end up learning a lot of new things.&lt;/p&gt;

&lt;p&gt;Our current project is one of those. It has a web platform, iOS and Android applications, a public webstream, and a dozen different user roles. All of those platforms are interconnected and depend on each other, especially with time events where one platform has to pass the information to another in an exact given time frame.&lt;/p&gt;

&lt;p&gt;We use the BDD approach on this project — the software tester is included in every aspect of the project, the team is writing user stories, some of the stories are automated, and every user story/feature is manually tested by a software tester. This approach worked well when testing the applications and the features, separately, one by one. However, when we tried to use the platform, all the applications together, we saw that lots of bugs caused by miscommunication or misalignment between the applications could be found. The only way to overcome this testing obstacle was to include more people in the testing process because it could not be done by just one or two software testers.&lt;/p&gt;

&lt;p&gt;So, we decided to start exploratory testing sessions with the whole project team. Everyone was included in testing — software developers, project managers, designers, even the CEO. The software tester made the test cases in TestRail and handed out them to the team to give feedback after the testing session. Then the tester would review the feedback and open the bug tasks for fixing. &lt;/p&gt;

&lt;p&gt;What else did we gain from this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We managed to get to the state where more people are using the platform and get their feedback&lt;/li&gt;
&lt;li&gt;In a smaller group, we managed to simulate a real user test&lt;/li&gt;
&lt;li&gt;The project team got a chance to learn more about the platform's functionality and its features — the fronted/web platform developer got a chance to use mobile applications and vice versa, designers got a chance to see how their design is behaving in the app and the project managers got a chance to see the real state of the project&lt;/li&gt;
&lt;li&gt;The developers got a chance to reproduce the reported bugs together with software testers and to understand them better&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These sessions were both fun and useful for our project team. Feel free to share your thoughts if you have had a similar situation.&lt;/p&gt;

</description>
      <category>engineeringmonday</category>
      <category>testing</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>BDD Game: Importance of Shared Understanding</title>
      <dc:creator>Ajdin Mustafić</dc:creator>
      <pubDate>Mon, 21 Dec 2020 16:46:56 +0000</pubDate>
      <link>https://forem.com/bornfightcompany/bdd-game-importance-of-shared-understanding-50ob</link>
      <guid>https://forem.com/bornfightcompany/bdd-game-importance-of-shared-understanding-50ob</guid>
      <description>&lt;p&gt;At Bornfight, we started using &lt;em&gt;Behavior Driven Development&lt;/em&gt; on our projects, about six months ago. From the very beginning, every member of the project team could see the benefit of using BDD. However, it can sometimes be hard to get everyone on board, especially when it comes to having all the project members to talk about features/BDD stories. And if we are not &lt;strong&gt;collaborating&lt;/strong&gt; and not talking about the features, we can not get a &lt;strong&gt;shared understanding&lt;/strong&gt; of the features. If we do not get a shared understanding, we are not doing BDD!&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;To overcome this obstacle and to see the true value of collaboration and shared understanding, on one of our sprint retrospective meetings, we decided to play BDD - Shared Understanding game.&lt;/p&gt;

&lt;p&gt;The game is very easy to play, but the benefits are far greater. Basically, we needed one person to make some basic drawing (designer) and the other person (project manager) to look at the drawing and take a note (acceptance criteria). After taking a note, the project manager handed us the acceptance criteria and without showing us the drawing asked us to draw it down. We were two backend developers, one fronted developer, a software tester, and another designer.&lt;/p&gt;

&lt;p&gt;These were the acceptance criteria:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A large empty circle is located above the horizontal half of the frame, closer to the middle.&lt;/li&gt;
&lt;li&gt;In a large empty circle, a little above and a little to the right of the middle there is a small filled circle.&lt;/li&gt;
&lt;li&gt;In the plane with a small circle there are 2 small filled circles, one next to the other, but outside the large circle.&lt;/li&gt;
&lt;li&gt;The left small circle outside the circle is shaded.&lt;/li&gt;
&lt;li&gt;Parallel to the small circle inside the large circle, above, at the top of the frame, there is another small circle that is slightly smaller than the small circles inside the large circle.&lt;/li&gt;
&lt;li&gt;2 straight lines are drawn from the middle of a large empty circle, one goes straight down to the bottom - a parallel line, and the other, horizontal line, goes to the edge of the left frame.
(Feel free to try it yourself before looking at our results.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The original was drawn in Figma by one of our designers but the rest of the team could use whatever preferred, Figma or pen and the paper.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;This was the original drawing:&lt;/p&gt;

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

&lt;p&gt;And this is how each member of the team perceived by following &lt;strong&gt;only&lt;/strong&gt; the acceptance criteria:&lt;/p&gt;

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

&lt;p&gt;After seeing the original and then seeing each other's drawings we were amazed how everyone understood, the same text, differently. And this was our &lt;strong&gt;conclusion&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A picture is worth a thousand words.&lt;/li&gt;
&lt;li&gt;It is very important to write clear and accurate acceptance criteria.&lt;/li&gt;
&lt;li&gt;It is important to build a common language.&lt;/li&gt;
&lt;li&gt;We drew some things based on the assumption and some of them were correct by pure luck.&lt;/li&gt;
&lt;li&gt;It is important to revise the acceptance criteria together.&lt;/li&gt;
&lt;li&gt;We all think differently and perceive what we read differently.&lt;/li&gt;
&lt;li&gt;Different perspectives are not bad. They give us a broader picture and new ideas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The most important thing is to gain a shared understanding.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So if you work on complex software, when you get the acceptance criteria, talk it through with your project team and make sure that everyone understood it correctly. Otherwise, you can end up dealing with a lot of bugs or even worse, with useless software.&lt;/p&gt;

&lt;p&gt;Feel free to contact us if you need help or you'd like to discuss Behavior Driven Development concepts.&lt;/p&gt;

</description>
      <category>engineeringmonday</category>
      <category>bdd</category>
      <category>agile</category>
      <category>testing</category>
    </item>
    <item>
      <title>Time Manipulation in Software Testing</title>
      <dc:creator>Ajdin Mustafić</dc:creator>
      <pubDate>Mon, 28 Sep 2020 09:29:44 +0000</pubDate>
      <link>https://forem.com/bornfightcompany/time-manipulation-in-software-testing-a60</link>
      <guid>https://forem.com/bornfightcompany/time-manipulation-in-software-testing-a60</guid>
      <description>&lt;p&gt;As a software tester you probably already know how important it is to test software’s &lt;strong&gt;behavior&lt;/strong&gt; under different circumstances. One of those circumstances may be watching your software perform while you manipulate with &lt;strong&gt;time&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;You can time travel to future or past dates, different time zones, leap year, end of the year, month, billing cycle, test the daylight saving time, or just fast-forward to the time that your software requires to finish some action. If you don't want to do any changes to your code, change the system clock, or isolate the server then you should find yourself a tool that will help you.&lt;/p&gt;

&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Early bug discovery in software development - There are some test case examples where you would need to wait for some time to see the outcome of your test. For example, you want to get a notification in your software one day before the end of the month. Instead of waiting, just change the date.&lt;/li&gt;
&lt;li&gt;Discovering possible future miscalculations in reports - You can speed up the time to see how will your software behave based upon the parameters that you have entered.&lt;/li&gt;
&lt;li&gt;Financial validation - Validate your finances at any point in time in the future.&lt;/li&gt;
&lt;li&gt;Workflows testing - See how the events in your workflow will look before you reach them in real-time.&lt;/li&gt;
&lt;li&gt;Policy expiration testing - Check if your clients will be notified when the policy expiration date is near.&lt;/li&gt;
&lt;li&gt;Data aging/archiving - Check if the data will be archived in the given time.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you want to expand your testing possibilities, time manipulation software tools are definitely the way to go. Besides you can use them in your automated tests as well.&lt;/p&gt;

&lt;p&gt;To start with, you can check some of these tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.vornexinc.com"&gt;TimeShiftX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://solution-soft.com/products/time-machine"&gt;Time Machine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.serialporttool.com/GK/time-travel"&gt;Serial Port Tool&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feel free to share your experience with us if you have already tried using or even automating these kinds of tools.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>todayisearched</category>
      <category>qualityassurance</category>
      <category>engineeringmonday</category>
    </item>
    <item>
      <title>Cypress Tests in BDD Style</title>
      <dc:creator>Ajdin Mustafić</dc:creator>
      <pubDate>Mon, 27 Jul 2020 11:34:37 +0000</pubDate>
      <link>https://forem.com/bornfightcompany/cypress-tests-in-bdd-style-52n5</link>
      <guid>https://forem.com/bornfightcompany/cypress-tests-in-bdd-style-52n5</guid>
      <description>&lt;p&gt;&lt;strong&gt;Behavior-driven development&lt;/strong&gt; is an Agile software development process that promotes collaboration between developers, software testers (QA), and the non-technical, business side in a software development process. The outcomes of their collaboration are structured &lt;strong&gt;behavior stories&lt;/strong&gt; which are requirements for product owners, acceptance criteria for developers, description for stakeholders, test cases, and automation scripts for testers.&lt;br&gt;
If you write your automated tests in &lt;strong&gt;Cypress&lt;/strong&gt; and you would like to run them in BDD stories style, you will need to do some additional steps:&lt;br&gt;
1) First, you need to install cypress with cucumber preprocessor module with this command:&lt;br&gt;
&lt;code&gt;$ npm install cypress cucumber cypress-cucumber-preprocessor&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;2) Then you need to define in your package.json how will you open Cypress:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;“scripts”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;“cypress-run-cucumber”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“cypress&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;--config-file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;cypress/cypress-cucumber.json”&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can simply start cypress with command &lt;code&gt;npm cypress-run-cucumber&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is our example of cypress-cucumber.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="err"&gt;“baseUrl”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“http://localhost:&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="err"&gt;“integrationFolder”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“cypress/tests/BDD”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="err"&gt;“pluginsFile”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“cypress/plugins/cucumber-plugins.js”&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And our cucumber-plugins.js looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cucumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;cypress&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;cucumber&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;preprocessor&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="c1"&gt;//on is used to hook into various events Cypress emits&lt;/span&gt;
   &lt;span class="c1"&gt;//config is the resolved Cypress config&lt;/span&gt;
   &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;preprocessor&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cucumber&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="na"&gt;fixturesFolder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;cypress&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;fixtures&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;integrationFolder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;cypress&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;tests&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;BDD&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;screenshotsFolder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;cypress&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;screenshots&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;videosFolder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;cypress&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;videos&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;supportFile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;cypress&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;support&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3) Also, in your package.json file you should define the path to your step definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;“cypress-cucumber-preprocessor”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;“nonGlobalStepDefinitions”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;“step_definitions”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“cypress/tests/BDD”&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4) It is also important to create .feature and .js file with the same name, where .js file must be in a folder, also with the same name. So, for example, you will have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;login.feature&lt;/li&gt;
&lt;li&gt;login (folder)

&lt;ul&gt;
&lt;li&gt;login.js&lt;/li&gt;
&lt;/ul&gt;


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

&lt;p&gt;In login.feature file you can simply paste the BDD story which was the outcome of your team collaboration and in login.js file you should define the steps with Cypress for that story.&lt;br&gt;
Example:&lt;br&gt;
This is your login.feature file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Feature: User Login
  In order to use the application
  As a user
  I need to be logged in
    Scenario: User logs in with correct credentials
    Given the user is on the login page
    When the user tries to login with correct credentials
    Then he should be redirected to the homepage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is your login.js file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Given&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;When&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;Then&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;cypress&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;cucumber&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;preprocessor&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;Given&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^the user is on login page$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;login&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;include&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;login&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;When&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^the user tries to login with correct credentials$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;tester&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;bornfight&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;com&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;pw&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;test123&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;Then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^he should be redirected to the homepage$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;include&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;home&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Feel free to comment below if you need any additional explanation or you would like to share your experience on this topic.&lt;/p&gt;

</description>
      <category>engineeringmonday</category>
      <category>cypress</category>
      <category>bdd</category>
      <category>testing</category>
    </item>
    <item>
      <title>Behavior-Driven Development: how to find bugs before coding starts</title>
      <dc:creator>Ajdin Mustafić</dc:creator>
      <pubDate>Tue, 17 Mar 2020 09:51:08 +0000</pubDate>
      <link>https://forem.com/bornfightcompany/behavior-driven-development-how-to-find-bugs-before-coding-starts-1o1d</link>
      <guid>https://forem.com/bornfightcompany/behavior-driven-development-how-to-find-bugs-before-coding-starts-1o1d</guid>
      <description>&lt;h2&gt;
  
  
  Quality of software should be taken care of from the very beginning of a project. That’s the core of Behavior-Driven Development!
&lt;/h2&gt;

&lt;p&gt;Quality is not something that you add when the project is almost done. Like, let’s add 5 sugar spoons of quality, stir it up and pass it to users. You can compare that to adding a Quality Assurance team to a project when most of the software features have already been developed and changing them would require too much time and effort. &lt;strong&gt;Behavior-Driven Development can help you find bugs by involving the QA team and their observation power in the initial state of the project.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Behavior-Driven Development
&lt;/h3&gt;

&lt;p&gt;Behavior-Driven Development is an agile software development process that promotes collaboration between developers, software testers (QA) and the non-technical, business side in a software development process. Those three parties, in the BDD process, are usually referred to as The Three Amigos. Their goal is to, by means of collaboration, eliminate all the possible errors in the software – even before any line of code is written.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WBoJNybR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.nicepng.com/png/full/350-3500238_three-amigos-image-chevy-chase-three-amigos-authentic.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WBoJNybR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.nicepng.com/png/full/350-3500238_three-amigos-image-chevy-chase-three-amigos-authentic.png" alt="Image: Three Amigos" width="880" height="487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How do they do it?
&lt;/h3&gt;

&lt;p&gt;BDD has emerged from Test-Driven Development, which is also a test-first approach, whose tests aim to check the application’s functionality (unlike BDD whose tests aim to test the actual behavior of the system from a user’s perspective).&lt;/p&gt;

&lt;p&gt;In order to be able to test the behavior of the system, Three Amigos get together, brainstorm and write potential behavior scenarios for testing. The scenarios should be written in plain language that everyone on the project can easily write and understand – both technical and non-technical people, from clients to testers. Furthermore, to avoid misunderstandings, but also to improve quality and avoid missed deadlines, The Three Amigos meet regularly to discuss how the product will be developed.&lt;/p&gt;

&lt;h3&gt;
  
  
  How each of the Three Amigos contribute to writing scenarios?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Business&lt;/strong&gt; (Business Analysts, Product Owner, Project Manager) – answers to questions like “what problem must be solved”. They provide requirements and they don’t need to have technical knowledge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Development&lt;/strong&gt; – answers to questions like “how will the solution be implemented”. They are technical experts and they build the software.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing&lt;/strong&gt; (Quality Assurance) – verifies that the software works correctly. They need to have some technical knowledge, but not as much as Development.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Behavior-Driven Development Process
&lt;/h3&gt;

&lt;p&gt;At the beginning of the BDD process, the product owner gets as much information as possible about users and their needs. Then The Three Amigos get together and work out the requirements and write structured scenarios in plain English language that anyone can understand.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3LsZrcY_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://image.slidesharecdn.com/bddsapfiori-170412093545/95/behaviour-driven-development-bdd-closing-the-loop-on-a-great-fiori-ux-13-638.jpg%3Fcb%3D1491989806" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3LsZrcY_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://image.slidesharecdn.com/bddsapfiori-170412093545/95/behaviour-driven-development-bdd-closing-the-loop-on-a-great-fiori-ux-13-638.jpg%3Fcb%3D1491989806" alt="Image: Behaviour driven development" width="638" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Written scenarios keep developers focused on delivering precisely what the product owner wants, because the scenarios act like their acceptance criteria and a lodestar during the development process.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For testers, those scenarios can be a base for writing test cases and automated test scripts. This speeds up the testing process and helps achieve greater test coverage.&lt;/p&gt;

&lt;p&gt;Product owner shows the scenarios to the user, client or other stakeholders – as they can easily understand what’s written, they can confirm that these scenarios describe exactly what the software should do, or not.&lt;/p&gt;

&lt;p&gt;Scenarios written in plain language guarantee that all the people on project, at any point in time, clearly understand what are the requirements and how the software should behave. This helps to avoid any misunderstandings and games of broken telephones. Another outcome is that you have structured and executable documentation, which is very helpful when you need to bring new people to the project or when two different teams build software and do the maintenance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here is one made up example – scenario for a feature “Mobile Account top up with credit card” written in plain language called Gherkin.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Feature:&lt;/strong&gt; Mobile Account top up with credit card&lt;br&gt;
In order to top up my mobile account with credit card&lt;br&gt;
As a mobile user&lt;br&gt;
I need to have a valid credit card with sufficient funds&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; Credit card account has sufficient funds&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Given&lt;/strong&gt; the credit card has sufficient funds&lt;br&gt;
&lt;strong&gt;And&lt;/strong&gt; the card is valid&lt;br&gt;
&lt;strong&gt;And&lt;/strong&gt; the mobile account balance is 5€&lt;br&gt;
&lt;strong&gt;And&lt;/strong&gt; the user enters a valid mobile phone number on the top up page&lt;br&gt;
&lt;strong&gt;When&lt;/strong&gt; the user confirms mobile phone number&lt;br&gt;
&lt;strong&gt;And&lt;/strong&gt; chooses 15€ top up&lt;br&gt;
&lt;strong&gt;And&lt;/strong&gt; enters the correct credit card details&lt;br&gt;
&lt;strong&gt;Then&lt;/strong&gt; the user should see a successful top up message&lt;br&gt;
&lt;strong&gt;And&lt;/strong&gt; the mobile account balance should be 20€&lt;/p&gt;

&lt;p&gt;After reading this scenario and the scenario steps, you can easily understand how the feature should behave when the user has sufficient funds on their credit card account. In order to prevent bugs from happening, our goal is to cover as many scenarios as possible. Also, we can use them afterwards to verify that the feature works correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So, for this feature we could also describe scenarios like “user doesn’t have enough money on his account”, “user doesn’t have a valid credit card” or “user’s sim card is inactive”…and many others.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  BDD solves the problem of QA becoming agile..
&lt;/h3&gt;

&lt;p&gt;Some companies are still struggling to include a QA team in their agile process, and even though they are doing agile, QA starts with testing and finding bugs at the very end of the software development process. This is usually an expensive and more time-consuming approach. And it is not always just the bugs – sometimes the project team wanders off from the real software objective trying to impress the clients. It’s like building a spaceship for a user that just wanted a Vespa to go to work. These kinds of problems can be recognized by writing behavior scenarios, which is where the QA role comes into play. With their ability to put themselves into users’ perspective, they can advise different behavior scenarios in order to make sure that the project goes in the right direction and to eliminate the “what if?” kinds of questions as early as possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenges
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;As BDD is based on collaboration, one of the biggest challenges is that it requires a high level of business engagement and it is usually hard to get business parties to start to collaborate on this level.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;BDD pairs nicely with agile software development, but it’s really hard to use it with waterfall – and that is one of its downsides. Another one is that you need to have all of your project people in one place and always on the same page, so it is nearly impossible to outsource, for example, backend developers or a QA team.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;If you are doing agile in your software development process, Behavior-Driven Development is an add-on that is worth considering. It could save you trouble finding high-severity bugs during the development process or even after the coding is finished. BDD increases the quality of the software and steers your project in the right direction. Furthermore, it makes it easier to include your QA team in every sprint of the agile process.&lt;/p&gt;

&lt;p&gt;If you want to learn more about BDD, check out some of these articles:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://automationpanda.com/2017/02/20/the-behavior-driven-three-amigos/"&gt;The behavior driven three amigos&lt;/a&gt;&lt;br&gt;
&lt;a href="https://automationpanda.com/2017/01/30/bdd-101-writing-good-gherkin/"&gt;BDD 101: writing good Gherkin&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.departmentofproduct.com/blog/writing-bdd-test-scenarios/"&gt;Writing BDD test scenarios&lt;/a&gt;&lt;br&gt;
&lt;a href="https://codeception.com/docs/07-BDD"&gt;Behavior Driven Development&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.ustwo.com/blog/designers-and-behaviour-driven-development"&gt;Why should designers care about behavior driven development&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
&lt;a href="https://atesterthing.wordpress.com/2019/03/10/behaviour-driven-development-bdd/"&gt;Behaviour Driven Development – BDD&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.manning.com/books/bdd-in-action"&gt;BDD in action&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;We’re available for partnerships and open for new projects. &lt;br&gt;
&lt;a href="https://www.bornfight.com/contact/"&gt;If you have an idea you’d like to discuss, share it with our team!&lt;/a&gt;&lt;/p&gt;

</description>
      <category>softwaredevelopement</category>
      <category>dev</category>
      <category>software</category>
      <category>bdd</category>
    </item>
  </channel>
</rss>
