<?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: Talank</title>
    <description>The latest articles on Forem by Talank (@talank).</description>
    <link>https://forem.com/talank</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%2F337454%2F303eec93-f070-46b8-a4c8-a589e9e48e50.jpeg</url>
      <title>Forem: Talank</title>
      <link>https://forem.com/talank</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/talank"/>
    <language>en</language>
    <item>
      <title>Best Practices in Regression Testing for Beginners</title>
      <dc:creator>Talank</dc:creator>
      <pubDate>Tue, 11 Jan 2022 03:42:29 +0000</pubDate>
      <link>https://forem.com/talank/best-practices-in-regression-testing-for-beginners-4n3m</link>
      <guid>https://forem.com/talank/best-practices-in-regression-testing-for-beginners-4n3m</guid>
      <description>&lt;p&gt;Change is a vital process in software maintenance, and during changes, new bugs might occur. Even if you carried out a thousand different test scenarios before releasing the first version of the software, it is not guaranteed that the second version does not require any of those tests to be re-executed. This is because fixing new bugs might cause some older bugs that were fixed in an earlier release to reappear. &lt;/p&gt;

&lt;p&gt;So, to ensure that old bugs have not resurfaced, we conduct regression testing. Regression testing is the testing that is done before finalizing any changes in the source code of the software. &lt;/p&gt;

&lt;p&gt;There are several levels of tests, for example, unit tests, integration tests, end-to-end tests, etc. And regression tests could comprise any of these tests. It is not about the level of tests or the type of tests, but about the time when the tests are done and the depth of tests. It is about time because the regression test is done before any changes are merged or deployed. As for the depth, the greater the coverage, the better the quality assurance. &lt;/p&gt;

&lt;p&gt;Nevertheless, it may become very tedious to manually test all the scenarios from a test plan if the number of test scenarios is very high. A solution to this problem is &lt;a href="https://www.perfecto.io/blog/automated-regression-testing"&gt;automated regression testing&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;You might have already heard some buzzwords around this topic, such as BDD, TDD, test report, bug tracking, etc. Many tools and technologies can indeed be used to automate testing your software. But, my advice is that you should not get intimidated by these tools and technologies while you are a beginner in regression testing. &lt;/p&gt;

&lt;p&gt;Regression testing is mainly about re-executing the tests several times. Sometimes, it might not be possible to execute all the tests, so you might have to categorize the test cases based on their priorities and context as a tester.&lt;/p&gt;

&lt;p&gt;If you are in the starting phase of your software testing career, then I can give you the following tips to perform regression testing in the best way possible.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Automate as much as possible
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0KrbH8gf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p2cfzj42yb5igvcthpg1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0KrbH8gf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p2cfzj42yb5igvcthpg1.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;a href="https://www.testing-whiz.com/blog/understanding-the-dynamics-of-automation-testing-when-how-and-why"&gt;source&lt;/a&gt;&lt;/center&gt;
&lt;br&gt;
One of the &lt;a href="https://www.geeksforgeeks.org/software-engineering-seven-principles-of-software-testing/"&gt;seven principles of software testing&lt;/a&gt; states that “Exhaustive testing is not possible”; however, it is always better to test as much as we can. And automating as many tests as possible makes the process of regression testing a lot faster. So you should try to increase test coverage with more automated tests. 

&lt;p&gt;And add varieties of tests. Do not just write unit tests, although they catch more bugs than any other tests. You should write end-to-end tests as well that reflect the user stories.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Run tests in some CI servers and run them parallelly
&lt;/h4&gt;

&lt;p&gt;Automated regression tests should be executed before any pull request is merged into a base branch. As the number of tests increases, these tests might take hours to complete execution. So, instead of running the tests each time in a local machine, we run them in the CI servers, such as Travis, Drone, GitHub Actions, etc. Finally, as far as possible, run the tests concurrently so that developers do not have to wait long for the test to be done.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Maintain your test because the AUT is changing the behavior
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X-LKRSA8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/df52u33a42qsvdp0y1xx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X-LKRSA8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/df52u33a42qsvdp0y1xx.png" alt="Image description" width="850" height="514"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;a href="https://www.researchgate.net/figure/Different-Viewpoints-on-the-Application-Under-Test_fig4_259635976"&gt;source&lt;/a&gt;&lt;/center&gt;
&lt;br&gt;
Once you automate your test scenarios, you should run the test on each commit and maintain the taste according to the changes made in each commit. If the change is unintentional, then the taste fails, which will notify the developer that the regression test detected a new bug. And if the change is intentional, then the test might fail, in which case software testers should maintain the test scenario to comply with the new behavior of the application under test (&lt;a href="https://innoroo.com/blog/2018/11/22/application-under-test-glossary/"&gt;AUT&lt;/a&gt;).
&lt;h4&gt;
  
  
  4. Priorities the tests because running each test becomes time-consuming
&lt;/h4&gt;

&lt;p&gt;After you automate a lot of test cases, you should prioritize those tests so that the most important tests are executed in every commit. For this purpose, you can tag your tests based on the area that it covers. One of the popular tags is “smokeTest”, which is used to indicate that the test is very basic and there is no point in executing other tests if the &lt;a href="https://www.guru99.com/smoke-testing.html"&gt;smoke test&lt;/a&gt; fails. If you tag your tests based on the context, you can execute the tests only if the changes are related to that context. It will save a significant amount of time.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. Don't skip the test that caught some bugs previously
&lt;/h4&gt;

&lt;p&gt;The defect clustering principle of software testing explains that almost 80% of the defects are centered around 20% of the code (or module). So, if a test finds some bug, you should run that test on each regression test because it is highly likely that the same test will catch a similar bug.&lt;/p&gt;

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

&lt;p&gt;In a nutshell, regression testing requires tests to be executed multiple times throughout the &lt;a href="https://stackify.com/what-is-sdlc/"&gt;SDLC&lt;/a&gt;. So, to avoid boredom and increase the efficiency of your work, you should try to automate as many tests as you can. Similarly, classify the tests and set the priorities so that you would know which tests must be executed for change in particular modules.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Visual Regression Test with Nigthwatch VRT</title>
      <dc:creator>Talank</dc:creator>
      <pubDate>Wed, 03 Nov 2021 07:40:26 +0000</pubDate>
      <link>https://forem.com/jankaritech/visual-regression-test-with-nigthwatch-vrt-3h33</link>
      <guid>https://forem.com/jankaritech/visual-regression-test-with-nigthwatch-vrt-3h33</guid>
      <description>&lt;p&gt;Firstly, if you don't have any idea about what Visual Regression Test (VRT) is then I would recommend that you read my previous blog &lt;a href="https://dev.to/jankaritech/insight-to-visual-regression-testing-25mh"&gt;Insight to Visual Regression Testing&lt;/a&gt;. If you have already read that one or you already have some idea about "What is VRT?", then you are now ready to read this blog. The figure below (By &lt;a href="https://galaxyweblinks.com/" rel="noopener noreferrer"&gt;Galaxy Weblinks&lt;/a&gt;) also gives a basic idea about VRT and the various tools that can be used for automated VRT.&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%2Fuploads%2Farticles%2Fm3ihz3kt2nkvifr9xxnq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm3ihz3kt2nkvifr9xxnq.png" alt="Automation Testing Tools For Visual QA, By Galaxy Weblinks"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The definition of &lt;code&gt;nightwatch-vrt&lt;/code&gt; is quite clear from its name. It is a VRT tool that works as an extension to &lt;a href="https://nightwatchjs.org/" rel="noopener noreferrer"&gt;nightwatch.js&lt;/a&gt;. Using &lt;code&gt;nightwatch-vrt&lt;/code&gt; is pretty straightforward. You only need to invoke the &lt;code&gt;screenshotIdenticalToBaseline&lt;/code&gt; function to make a comparison of the current screenshot with the respective baseline image. And if you look at the internal &lt;a href="https://github.com/Talank/nightwatch-vrt/blob/master/assertions/screenshotIdenticalToBaseline.js" rel="noopener noreferrer"&gt;logic&lt;/a&gt; of this function then you will find that all it does is wait for an element to be present, then capture the screenshot of that element, compare it with the baseline, and finally return the comparison result. And if you look further into the image comparison logic then you will notice that &lt;code&gt;nightwatch-vrt&lt;/code&gt; actually uses &lt;a href="https://www.npmjs.com/package/jimp" rel="noopener noreferrer"&gt;JIMP&lt;/a&gt; (JavaScript Image Manipulation Program) which is built with Javascript with no native dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;As I already said that &lt;code&gt;nightwatch-vrt&lt;/code&gt; is an extension to the &lt;code&gt;nightwatch.js&lt;/code&gt;, you first need to setup nightwatch.js. And if you don't know how to setup &lt;code&gt;nightwatch.js&lt;/code&gt; then you can refer to one of my previous blogs &lt;a href="https://dev.to/jankaritech/setup-nightwatch-and-run-your-first-test-o7o"&gt;Setup Nightwatch and run your first test&lt;br&gt;
&lt;/a&gt;. Next, add nightwatch-vrt in the devDependencies of your project. You can do it using the following command using yarn.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add --dev nightwatch-vrt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you need to add/edit the &lt;code&gt;custom_commands_path&lt;/code&gt; and &lt;code&gt;custom_assertions_path&lt;/code&gt; in your nightwatch configuration file as follows.&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="nx"&gt;custom_commands_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node_modules/nightwatch-vrt/commands&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="nx"&gt;custom_assertions_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node_modules/nightwatch-vrt/assertions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In addition to the above-mentioned setup, you also need to add &lt;code&gt;visual_regression_settings&lt;/code&gt; to the nightwatch configuration file's &lt;code&gt;globals&lt;/code&gt; section as follows.&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="nx"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nl"&gt;visual_regression_settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;generate_screenshot_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;generateScreenshotFilePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;latest_screenshots_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tests/vrt/latest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;baseline_screenshots_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tests/vrt/baseline&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;diff_screenshots_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tests/vrt/diff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.02&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;always_save_diff_screenshot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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;And you also need to define the function that you specified in &lt;code&gt;generate_screenshot_path&lt;/code&gt;. For example, in the above configuration, I have used the function &lt;code&gt;generateScreenshotFilePath&lt;/code&gt; which I defined as follows.&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;function&lt;/span&gt; &lt;span class="nf"&gt;generateScreenshotFilePath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nightwatchClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;basePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;imagePath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;basePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;imagePath&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;We pass a function to &lt;code&gt;generate_screenshot_path&lt;/code&gt; because the VRT screenshot path generator option accepts a function that returns a string containing the full path based on the test properties. We can not provide a constant string instead of the path generator function because not all tests use the same screenshot.&lt;/p&gt;

&lt;p&gt;So the above configuration stores the baseline, latest, and diff images in the subfolders &lt;code&gt;tests/vrt/baseline&lt;/code&gt;, &lt;code&gt;tests/vrt/latest&lt;/code&gt;, and &lt;code&gt;tests/vrt/diff&lt;/code&gt; respectively. If we provide a common path for baseline, diff and latest images then we should provide some optional configurations such as suffix to distinguish the images. These optional configurations are &lt;code&gt;baseline_suffix&lt;/code&gt;, &lt;code&gt;diff_suffix&lt;/code&gt;, and &lt;code&gt;latest_suffix&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;threshold&lt;/code&gt; option in the &lt;code&gt;visual_regression_settings&lt;/code&gt; specifies how sensitive the image comparison will be. To understand what all other options mean, you can check out the README file of &lt;a href="https://github.com/Crunch-io/nightwatch-vrt" rel="noopener noreferrer"&gt;nightwatch-vrt github repository&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Write Tests
&lt;/h2&gt;

&lt;p&gt;As usual, we start writing our test by making the feature file at first, and the visual check can be done in the step definitions. For the demonstration, I am referencing &lt;a href="https://github.com/Talank/vrt-demo" rel="noopener noreferrer"&gt;this project&lt;/a&gt; which is a simple to-do app in react.&lt;/p&gt;

&lt;p&gt;One of the test scenarios in this app could be as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gherkin"&gt;&lt;code&gt;&lt;span class="kn"&gt;Scenario&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; toDo task add test
    &lt;span class="nf"&gt;Given &lt;/span&gt;the user has opened the home page
    &lt;span class="nf"&gt;When &lt;/span&gt;the user adds a new task &lt;span class="s"&gt;"New Task"&lt;/span&gt;
    &lt;span class="nf"&gt;Then &lt;/span&gt;the task &lt;span class="s"&gt;"New Task"&lt;/span&gt; should appear in the toDo list
    &lt;span class="nf"&gt;And &lt;/span&gt;the toDo form should match the default baseline
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the step &lt;code&gt;And the toDo form should match the default baseline&lt;/code&gt;, will perform the visual regression test, and so in the demonstration section, I will be done. And I will focus only on that step.&lt;/p&gt;

&lt;p&gt;The implementation of this step can look like the following:&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="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="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cucumber&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nightwatch-api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toDoFormSelector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#to-do-form&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;assertScreenShot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imgName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForElementVisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toDoFormSelector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;screenshotIdenticalToBaseline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;toDoFormSelector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;imgName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;`Matched the &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;imgName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; of toDo page`&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;Then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^the toDo form should match the default baseline$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;assertScreenShot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;todo-form&lt;/span&gt;&lt;span class="dl"&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;The &lt;code&gt;assertScreenShot&lt;/code&gt; function uses the command &lt;code&gt;screenshotIdenticalToBaseline()&lt;/code&gt; that is defined in the &lt;code&gt;nightwatch-vrt&lt;/code&gt; library. &lt;code&gt;screenshotIdenticalToBaseline&lt;/code&gt; could take up to 4 parameters where only the first parameter is mandatory:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first one is a String which is the selector of the element that should be tested visually.&lt;/li&gt;
&lt;li&gt;The second one is also a String which is the name of the image that is used for the name of the baseline, diff, or latest image. The default name is the name of the selector provided as the first parameter.&lt;/li&gt;
&lt;li&gt;The third one is NightwatchVRToptions settings that override the defaults and &lt;code&gt;visual_regression_settings&lt;/code&gt; of the nightwatch configuration file.&lt;/li&gt;
&lt;li&gt;And the fourth parameter is a String which is the message that is displayed in the console upon the successful completion of the test.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the VRT is executed for the first time, the baseline images do not exist and so they are created. When the test finds the baseline image with the appropriate name, it will compare the screenshot of the element with the respective image in the baseline. So, if you are running the test for the first time, it will execute twice, once to create the baseline images and again to compare the current state with the baseline. Next time when you run the test, it will be executed only once as the baseline is created only once. However, if there are some changes in the UI and the test fails, then you need to change the baseline image as well.&lt;/p&gt;

&lt;p&gt;There are mainly 2 ways to update your baseline image. The easiest way to do this is to set the configuration &lt;code&gt;always_save_diff_screenshot:&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; in the nightwatch configuration file's &lt;code&gt;globals&lt;/code&gt; section. This will update all the failing screenshots at once. If you need to update only one screenshot then the appropriate method to update it is to delete the baseline screenshot and run the tests again which will take the updated screenshot and save it as the new baseline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Execute the test
&lt;/h2&gt;

&lt;p&gt;You do not need any special commands to execute the VRT. You can execute the scenario containing the feature file like a normal nightwatch test and that's it. If you need help with setting up nightwatch and running the tests, you can read &lt;a href="https://dev.to/jankaritech/setup-nightwatch-and-run-your-first-test-o7o"&gt;this blog&lt;/a&gt; of mine. &lt;/p&gt;

</description>
      <category>visualtesting</category>
      <category>javascript</category>
      <category>testing</category>
    </item>
    <item>
      <title>Ride-sharing with geo-fencing technique</title>
      <dc:creator>Talank</dc:creator>
      <pubDate>Sun, 21 Mar 2021 13:08:01 +0000</pubDate>
      <link>https://forem.com/talank/ride-sharing-and-vehicle-tracking-with-geo-fencing-technique-132a</link>
      <guid>https://forem.com/talank/ride-sharing-and-vehicle-tracking-with-geo-fencing-technique-132a</guid>
      <description>&lt;p&gt;For the undergraduate final year's project, me and my team designed and implemented a taxi ride-sharing algorithm that is targeted at urban areas. In this blog, I am going to describe algorithms that we used for this project and all these algorithms are open source in my GitHub &lt;a href="https://github.com/Talank/VroomAlgorithm"&gt;(VroomAlgorithm)&lt;/a&gt;. If you are willing to further study these algorithms and if you have any confusion, or if you have any suggestions of improvement, then feel free to contact me.&lt;/p&gt;

&lt;p&gt;The major algorithms that we used in this ride-sharing system are as follows:&lt;/p&gt;

&lt;h2&gt;
  
  
  GEO-FENCING
&lt;/h2&gt;

&lt;p&gt;For vehicle searching, we have used the geo-fencing technique. In this technique, we divide the geographical area into multiple smaller areas (based on the district, for example) called ‘Major Fence’. Then we further divide the regions within ‘Major Fence’ into smaller manageable regions called ‘Minor Fence’(for example, city). The size of the ‘Minor Fence’ is determined by the traffic and point of interest. So we convert the vehicle searching problem to a mathematical problem to find if a point lies within a polygon, using the &lt;a href="http://geomalgorithms.com/a03-_inclusion.html"&gt;Winding number algorithm&lt;/a&gt;. We check if the location of the driver lies within the ‘Minor Fence’ and thus perform the ride-matching. In the figure below, I have shown an example of geo-fences.&lt;br&gt;
&lt;/p&gt;
&lt;center&gt;

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

&lt;p&gt;&lt;b&gt;Geo-fences Example(showing some fences in different color polygon)&lt;/b&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;


&lt;/center&gt;
&lt;h2&gt;
  
  
  RIDE MATCHING
&lt;/h2&gt;

&lt;p&gt;Ride matching is done with the help of geo-fencing. When a ride request is made in luxury mode(without sharing) or for a motorcycle, then at first, the ride request is forwarded only to the drivers who are available in the same fence. If no free driver is found inside the same fence, then the ride request is forwarded to the drivers in the neighboring fences. So, a single geofence data also contains some information about its 4 neighbors. For example:&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;name:&lt;/span&gt;&lt;span class="s2"&gt;"fence-name"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;topLeftX:&lt;/span&gt;&lt;span class="s2"&gt;"topLeftX-coordinate"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;topLeftY:&lt;/span&gt;&lt;span class="s2"&gt;"topLeftY-coordinate"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;topRightX:&lt;/span&gt;&lt;span class="s2"&gt;"topRightX-coordinate"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;topRightY:&lt;/span&gt;&lt;span class="s2"&gt;"topRightY-coordinate"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;bottomLeftX:&lt;/span&gt;&lt;span class="s2"&gt;"bottomLeftX-coordinate"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;bottomLeftY:&lt;/span&gt;&lt;span class="s2"&gt;"bottomLeftY-coordinate"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;bottomRightX:&lt;/span&gt;&lt;span class="s2"&gt;"bottomRightX-coordinate"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;bottomRightY:&lt;/span&gt;&lt;span class="s2"&gt;"bottomRightY-coordinate"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;neighbors:&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"left-neighbors"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"right-neighbors"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"bottom-neighbors"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"top-neighbors"&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;h2&gt;
  
  
  RIDE SHARING
&lt;/h2&gt;

&lt;p&gt;In this project, we used a progressive ride-sharing approach. Whenever a ride offer is created, the system generates the set of geo-fences whose sequence specifies the direction of the ride. The set of geo-fences is generated along the shortest route, between source and the destination, generated by Google Map API. To get the shortest route geo-fences N (the set of geo-fences composing of the route), the only departure and destination location is required. We apply the inverted index data structure on the mechanism of saving the ride’s node. Now whenever the ride request is generated, the system computes the geo-fences along the path of the pickup and drop-off location and checks the following three constraints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the ride pass through the pickup geo-fence?&lt;/li&gt;
&lt;li&gt;Does the sequence of geo-fence of the ride offer has the same direction as the sequence of geo-fence of the route between passenger’s pick-up and drop-off location?&lt;/li&gt;
&lt;li&gt;Does the vehicle that is offering the ride has enough empty seats?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The figures below show how &lt;code&gt;inverse index data structure&lt;/code&gt; can be used for finding path and direction in terms of geo-fences, and how this can be used for &lt;code&gt;shared ride matching&lt;/code&gt;.&lt;/p&gt;


&lt;center&gt;

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

&lt;p&gt;&lt;b&gt;Inverse Index Data Structure&lt;/b&gt;&lt;/p&gt;



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

&lt;p&gt;&lt;b&gt;Shared Ride Matching&lt;/b&gt;&lt;/p&gt;



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

&lt;p&gt;&lt;b&gt;Ride Matching and Fence Direction Update&lt;/b&gt;&lt;/p&gt;




&lt;/center&gt;

&lt;h2&gt;
  
  
  PRE-DEFINED AVAILABILITY CHECK
&lt;/h2&gt;

&lt;p&gt;A normal algorithm might not forward any ride request if the vehicle is full as per it's current situation. However, if we analyse it temporally, then it might be the case that the vehicle will have enough empty seat when it reaches the place(geo-fence) from which new ride request is created. Hece, it is nice to perform a pre-defined availability check.&lt;/p&gt;

&lt;p&gt;Let us assume that the number of empty seats available “A” in the vehicle is less than the number of seats requested “R” in the shared ride. Also, suppose that the geo-fence path of the ride matches with the customer’s ride request’s geo-fence path. Now, as per the predefined availability check, we check that how many passengers will be inside the vehicle going through the pickup fence of the requested ride.&lt;/p&gt;

&lt;p&gt;Let,&lt;br&gt;&lt;br&gt;
A = Available number of seats,&lt;br&gt;&lt;br&gt;
R = Requested number of seats,&lt;br&gt;&lt;br&gt;
Driver’s updated fence direction = {“N1”, “N2”, “N3”, “N4”...}&lt;br&gt;&lt;br&gt;
Requested ride’s fence direction = {“Nk”,“Nk+1”, “Nk+2”...}&lt;br&gt;&lt;br&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if A &amp;lt;= R at the time of ride request{
 if (Total seat - the number of passengers inside the vehicle 
 who will pass through the geo-fence “Nk”) &amp;lt;= R{
  forward the ride request to the driver
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;center&gt;

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

&lt;p&gt;&lt;b&gt;Pre-defined Availability Check.&lt;/b&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;




&lt;/center&gt;

&lt;h2&gt;
  
  
  FUTURE DIRECTION
&lt;/h2&gt;

&lt;p&gt;It would be nice to analyze the applicability of this approach. Also in addition to the abovementioned algorithms, temporal analysis (e.g time-series analysis) might be done in the data that is collected every day so that drivers will know which place will have higher ride requests at a certain time of the day. Or even better, the system does so and suggests drivers where to go for more ride requests. If the system does so then the drivers will be evenly distributed in the geo-fences based on the number of potential passengers. However, it might not be as easy as I have said and it is still a topic of research. &lt;/p&gt;

&lt;h2&gt;
  
  
  REFERENCES
&lt;/h2&gt;

&lt;p&gt;To come up with this algorithm, we took reference from the following papers for learning more about geo-fencing and managing ride sharing using the help of inverse index data structure.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;D. Suganthi, S. R. (2018). Vehicle Tracking with Geo Fencing on Android Platform. International Journal of Engineering Science and Computing, 16992-16995.&lt;/li&gt;
&lt;li&gt;S. Maximilian, S. H. (2016). A Matching Algorithm for Dynamic Ridesharing. Transportation Research Procedia 19, 272 – 285.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>livetracking</category>
      <category>geofencing</category>
      <category>ridesharing</category>
    </item>
    <item>
      <title>Insight to Visual Regression Testing</title>
      <dc:creator>Talank</dc:creator>
      <pubDate>Fri, 12 Mar 2021 04:38:14 +0000</pubDate>
      <link>https://forem.com/jankaritech/insight-to-visual-regression-testing-25mh</link>
      <guid>https://forem.com/jankaritech/insight-to-visual-regression-testing-25mh</guid>
      <description>&lt;p&gt;"What you see is what you get" -Flip Wilson&lt;/p&gt;

&lt;p&gt;Web UI is advancing every day, and so is test automation. But, there might be several bugs in your application's UI that automated functional testing often misses. Some of these are called visual errors. Visual errors do not mean logical faults in the software. These are the aesthetic flaws that cause interfaces to be displayed incorrectly and make the UX worse. Visual regression tests ensure that there isn't any unintended change in UI. For this, an initial screenshot (called baseline) of the application is captured then, in each successive test, the screenshot of the same component in the current state is compared with the baseline image. If any distinguished changes are encountered, then the test is marked as failed.&lt;/p&gt;

&lt;p&gt;It is crucial to know that VRT intends to specify the deviations in appearance only, and failed VRT does not imply that the application is functionally incorrect. For instance, while testing for the responsiveness of a web page, even if automation tools like nightwatch.js can find all the components, it can not be ensured that all those components are aligned properly. So, in the aforementioned scenario, VRT fails even though the function regression test passes.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does it work?
&lt;/h2&gt;

&lt;p&gt;The primal concept behind VRT is a comparison between two images. Some visual testing tools does pixel to pixel comparison only, whereas some other are more innovative that make use of computer vision to automatically manage baseline. However, UI does not appear exactly the same in all displays and pixel-to-pixel comparison becomes flakier. So to avoid zero-tolerance QA Engineers normally set the threshold to more than 0. In most of the VRT tools such as &lt;code&gt;nightwatch-vrt&lt;/code&gt;, the value of threshold ranges from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt; where a smaller value means more sensitive comparison.&lt;/p&gt;

&lt;p&gt;After comparing the latest state of UI elements with the baseline image, if some difference is found by the VRT tool, a difference image is produced so that testers can easily see the difference after the test failure. For example, as shown in the image below, the change in color of the &lt;code&gt;Add&lt;/code&gt; button is detected by &lt;code&gt;nightwatch-vrt&lt;/code&gt;.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Cons of VRT
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;By automating the VRT, there will be a rise in maintenance cost as we need to keep screenshots of the web interface updated with respect to different browsers, devices, operating systems, etc.&lt;/li&gt;
&lt;li&gt;Image comparison takes more time than normal assertions used in functional testing. Nevertheless, image comparison can lead to false-positive and unreliable results.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limitation of Automated VRT
&lt;/h2&gt;

&lt;p&gt;CSS animations are very important artifacts for the enhancement of UX. No matter how minor it is, functional animations such as ripple effect in buttons, text animations, animation in loading sign, etc promote user engagements and make an application interactive. But VRT tools that are currently available ignore these animations by either freezing frames, disabling animations, or simply ignoring the CSS transitions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools
&lt;/h2&gt;

&lt;p&gt;There are several free and commercially available tools for VRT. &lt;a href="https://visualregressiontesting.com/tools.html"&gt;Here&lt;/a&gt;, you can find a bigger list of these tools. In this blog, I am going to discuss only 3 tools (nightwatch-vrt, percy, and applitools)&lt;/p&gt;

&lt;h3&gt;
  
  
  Nightwatch-vrt
&lt;/h3&gt;

&lt;p&gt;Nightwatch-vrt is an open-source library to perform VRT. It is an extension to &lt;code&gt;nightwatch.js&lt;/code&gt; with some additional custom commands that compare the screenshot of a DOM element identified by a selector with the baseline image. If there is no baseline image for a particular DOM element, it creates one and uses that for future assertions.&lt;/p&gt;

&lt;p&gt;The working mechanism of nightwatch-vrt is quite straightforward. It uses JavaScript Image Manipulation Program &lt;a href="https://www.npmjs.com/package/jimp"&gt;Jimp&lt;/a&gt;, which is an image processing tool written in Javascript, to compare the current screenshot of a DOM element with the baseline image. The percentage difference in the two images is then compared with the threshold value to get the result of VRT.&lt;/p&gt;

&lt;p&gt;To know more about nightwatch-vrt, you can refer to &lt;a href="https://github.com/Crunch-io/nightwatch-vrt"&gt;their github repo&lt;/a&gt;, or you can stay tuned for my next blog.&lt;/p&gt;

&lt;h3&gt;
  
  
  Percy
&lt;/h3&gt;

&lt;p&gt;Percy is a commercial tool that can be used for VRT and its working mechanism is pretty advanced than that of nightwatch-vrt. It has a screenshot stabilization technique by freezing animated GIFs on the first frame and disables CSS animation and transition styles. For automated visual testing, web animations are responsible for false-positive results in many cases. There are 3 other methods(Handling dynamic data, Third-party fonts, and ignoring 1px diffs) that Percy uses for stabilization of screenshot and you can read details about it in &lt;a href="https://docs.percy.io/docs/freezing-dynamic-data"&gt;this documentation&lt;/a&gt;. And another advantage of this tool is that it provides SDKs that can be integrated with UI tests in several languages and testing tools like cypress, puppeteer, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Applitools
&lt;/h3&gt;

&lt;p&gt;Like Percy, Applitools is also a commercial platform that provides several functionalities for automated visual testing. Its visual testing library is called Applitools Eyes which can be implemented with different languages like Javascript, Java, PHP, etc. With its visual AI algorithm, &lt;code&gt;Applitools Eyes&lt;/code&gt; tries to distinguish visual bugs that are only visible to human eyes. By using the &lt;code&gt;layout algorithm&lt;/code&gt;, if testers specify certain regions on the page that contain &lt;code&gt;dynamic contents&lt;/code&gt; like date and time, Applitools can check only for layout but not the actual contents. Similarly, if you have some elements in your UI that contain animated GIFs or CSS animations, you can specify those regions as layouts and Applitools will only check for the element to be visible, but ignores the animation. &lt;/p&gt;

&lt;p&gt;To learn more about its visual AI algorithms, you can refer to &lt;a href="https://applitools.com/applitools-ai-and-deep-learning/"&gt;this documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I hope you get some basic ideas about VRT, its pros, cons, and shortcomings. In my next blog, I will show you how to start implementing VRT using &lt;code&gt;nightwatch-vrt&lt;/code&gt;. Until then, happy coding.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>vrt</category>
      <category>imageprocessing</category>
    </item>
    <item>
      <title>Testing with Jest and Puppeteer</title>
      <dc:creator>Talank</dc:creator>
      <pubDate>Wed, 22 Jul 2020 10:56:45 +0000</pubDate>
      <link>https://forem.com/jankaritech/testing-with-jest-and-puppeteer-56k</link>
      <guid>https://forem.com/jankaritech/testing-with-jest-and-puppeteer-56k</guid>
      <description>&lt;p&gt;"In Jest, there is truth" -William Shakespeare.&lt;/p&gt;

&lt;p&gt;By using Jest, you will know the truth about your application. The &lt;code&gt;Jest&lt;/code&gt; is a javascript testing tool that is installed via NPM or Yarn and run via the command line. It is a great testing library and many react team members are involved building it, so it happens to work very well for testing react applications. Jest is built on top of Jasmine and Mocha but some additional features like snapshot testing and parallel test execution are provided by Jest. It also comes with built-in mocking and assertion abilities.&lt;/p&gt;

&lt;p&gt;Puppeteer is a Node library that is used for browser automation. Puppeteer provides a high-level API to control the browser. It can work with Chrome, Chromium, or Firefox. By default, this library runs the browser in headless mode, but it can be also configured to run Chrome or Chromium fully (non-headless).&lt;/p&gt;

&lt;h1&gt;
  
  
  Installation And Requirements
&lt;/h1&gt;

&lt;p&gt;This guide is based on Ubuntu 18.04. Some commands will be different if you have another OS installed on your computer. Before getting started with Jest, You need to have &lt;code&gt;npm&lt;/code&gt; and an app for which you will be writing tests.&lt;/p&gt;

&lt;p&gt;If your app is not yet ready for testing then you can just clone this basic &lt;a href="https://github.com/Talank/todo-react"&gt;todo app&lt;/a&gt; and follow along.&lt;/p&gt;

&lt;h3&gt;
  
  
  Jest Versions
&lt;/h3&gt;

&lt;p&gt;Jest is the test runner library for creating, executing, and structuring tests. Jest CLI is a tool that you use from the command line to run and provide configuration options to jest. It configures jest based on whatever argument you give while running jest. The version is important because jest is a dynamic library and different versions of jest might work differently. While writing this blog, I am using jest version &lt;code&gt;24.9.0&lt;/code&gt;. So, some features might be different if you are using some other version.&lt;/p&gt;

&lt;h3&gt;
  
  
  Jest installation and Running Tests
&lt;/h3&gt;

&lt;p&gt;You can install the latest version of jest from NPM using&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i jest --save-dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, its time to configure the NPM script for running a test from the command line. For this, open your &lt;code&gt;package.json&lt;/code&gt; and add the &lt;code&gt;test&lt;/code&gt; script as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&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="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jest"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Tests are run by using the Jest CLI (typing &lt;code&gt;jest&lt;/code&gt; followed by arguments in the command line). &lt;/p&gt;

&lt;p&gt;For example, in the &lt;a href="https://github.com/Talank/todo-react"&gt;todo app&lt;/a&gt; in my GitHub, you can run the test with the command &lt;code&gt;npm run test&lt;/code&gt; since I have added &lt;code&gt;"test": "jest"&lt;/code&gt; in the script of my &lt;code&gt;package.json&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;With the above-mentioned way, jest can be configured within your &lt;code&gt;package.json&lt;/code&gt;. That is the easy way for jest configuration. Alternatively, you can also use the jest configuration file for which you should create a &lt;code&gt;jest.config.js&lt;/code&gt; file and include that file in the command to run the test. For example, your package.json scripts section should include&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&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="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jest --config ./jest.config.js"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&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, in the root path alongside the package.json, your &lt;code&gt;jest.config.js&lt;/code&gt; should contain the following configurations&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&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="na"&gt;verbose&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;roots&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./__tests__&lt;/span&gt;&lt;span class="dl"&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;By using the jest configuration file, you have many other options as well. You can find the details about that in the &lt;a href="https://jestjs.io/docs/en/configuration"&gt;jest documentation&lt;/a&gt;. However, in this blog, I will focus on configuring jest using the &lt;code&gt;package.json&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Puppeteer
&lt;/h3&gt;

&lt;p&gt;Use the following command to install puppeteer in your project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i puppeteer --save-dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Puppeteer will download the latest version of chrome. If you need to work with firefox then you need to install the &lt;code&gt;puppeteer-firefox&lt;/code&gt; library. Refer to &lt;a href="https://www.npmjs.com/package/puppeteer-firefox"&gt;Puppeteer for Firefox&lt;/a&gt; in the npmjs website for further details.&lt;/p&gt;

&lt;p&gt;By the end of the installation of jest and puppeteer, you should have the following dependencies in the &lt;code&gt;devDependencies&lt;/code&gt; section of your &lt;code&gt;package.json&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"devDependencies"&lt;/span&gt;&lt;span class="p"&gt;:&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="nl"&gt;"jest"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^24.9.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;   
  &lt;/span&gt;&lt;span class="nl"&gt;"puppeteer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^4.0.1"&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;h3&gt;
  
  
  Creating Test Files
&lt;/h3&gt;

&lt;p&gt;The jest command runs the test files inside &lt;code&gt;__tests__&lt;/code&gt; folder or it will run any files with &lt;code&gt;.spec.js&lt;/code&gt; or &lt;code&gt;.test.js&lt;/code&gt; in their filename. So, you have to write your test in a file that ends with &lt;code&gt;.spec.js&lt;/code&gt; or &lt;code&gt;test.js&lt;/code&gt;. Or you can simply put all your tests inside the &lt;code&gt;__tests__&lt;/code&gt; folder.&lt;/p&gt;

&lt;h3&gt;
  
  
  Jest Globals
&lt;/h3&gt;

&lt;p&gt;There are varieties of jest Globals but we will mainly need 2 important globals called &lt;code&gt;describe&lt;/code&gt; and &lt;code&gt;it&lt;/code&gt;. The table below tells about these two globals in more detail.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;it&lt;/th&gt;
&lt;th&gt;describe&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AKA&lt;/td&gt;
&lt;td&gt;Tests&lt;/td&gt;
&lt;td&gt;Test Suite&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Syntax&lt;/td&gt;
&lt;td&gt;it(name, fn)&lt;/td&gt;
&lt;td&gt;describe(name, fn)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Description&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;it()&lt;/code&gt; global is a method in which you pass a function as an argument, that function is executed as a block of tests by the test runner. You describe your test logic inside &lt;code&gt;it()&lt;/code&gt; block.&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;describe&lt;/code&gt; is an optional method for grouping any number of &lt;code&gt;it()&lt;/code&gt; or test statements. &lt;code&gt;describe()&lt;/code&gt; block contains related it blocks.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In addition to &lt;code&gt;it()&lt;/code&gt; and &lt;code&gt;describe()&lt;/code&gt; methods, you might need the following methods to start testing with jest.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;afterAll(fn, timeout)&lt;/li&gt;
&lt;li&gt;afterEach(fn, timeout)&lt;/li&gt;
&lt;li&gt;beforeAll(fn, timeout)&lt;/li&gt;
&lt;li&gt;beforeEach(fn, timeout)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These functions are executed before and after the test scenarios. You can define these functions inside the &lt;code&gt;describe()&lt;/code&gt; method to make it applicable for all tests in the scope of that particular &lt;code&gt;describe()&lt;/code&gt; method.&lt;/p&gt;

&lt;h1&gt;
  
  
  Demo:
&lt;/h1&gt;

&lt;p&gt;Here I have added a test for adding a task in my react ToDo app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;puppeteer&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;puppeteer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Todo React&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;

  &lt;span class="nx"&gt;beforeAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&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="nx"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puppeteer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="nx"&gt;afterEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="nx"&gt;afterAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;add task to the list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&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="nx"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&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="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;newPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000&lt;/span&gt;&lt;span class="dl"&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;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should be possible to add task to the list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;taskInputField&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;//input[@placeholder="Enter task"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;taskToAdd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;New Task&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;taskInputField&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;taskInputField&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&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="nx"&gt;taskToAdd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keyboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;press&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Enter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lists&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;//div[@class='list']/p/input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;toDo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;lists&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;toDo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toDo&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;taskToAdd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation of Demo
&lt;/h3&gt;

&lt;p&gt;In the above demo, I first imported the puppeteer library. And in before scenario, I launched the browser in headless mode. Before all the scenarios inside the first describe block, the browser is launched only once. And before each scenario, a new tab is opened in incognito mode. Similarly, after each scenario, the tab is closed and when all the scenarios are executed, the browser is closed.&lt;/p&gt;

&lt;p&gt;The browser is launched in headless mode by default. However, if you want to launch the browser in non-headless mode then you can provide the browser launch option in &lt;code&gt;puppeteer.launch()&lt;/code&gt;. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puppeteer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;headless&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In Jest, there are plenty of functions to simulate UI activities. For example, in the above demo, you can see &lt;code&gt;click()&lt;/code&gt; for clicking in an element, &lt;code&gt;type()&lt;/code&gt; for typing, etc.&lt;/p&gt;

&lt;p&gt;Similarly, for assert operation, you can use &lt;code&gt;expect()&lt;/code&gt;. Many other matcher functions can be used with expect() such as &lt;code&gt;.toContain(item)&lt;/code&gt; , &lt;code&gt;toBeTruthy()&lt;/code&gt; etc. You can find more of these &lt;code&gt;jest matchers&lt;/code&gt; in the &lt;a href="https://jestjs.io/docs/en/expect"&gt;jest documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gherkin with Jest
&lt;/h3&gt;

&lt;p&gt;In Jest, you do not have to write a feature file for your test cases. If you need to write features in a separate file then you can use &lt;a href="https://github.com/bencompton/jest-cucumber"&gt;jest-cucumber&lt;/a&gt; library. By using this library, you can replace &lt;code&gt;describe&lt;/code&gt; and &lt;code&gt;it&lt;/code&gt; blocks by &lt;code&gt;Given&lt;/code&gt;, &lt;code&gt;When&lt;/code&gt;, and &lt;code&gt;Then&lt;/code&gt; step definitions. The step definitions are linked with the respective steps in the feature files. &lt;/p&gt;

&lt;p&gt;However, I would prefer &lt;code&gt;Codecept.js&lt;/code&gt; or &lt;code&gt;nightwatch.js&lt;/code&gt; instead of &lt;code&gt;jest&lt;/code&gt; if I need to use features of &lt;code&gt;Cucumber.js&lt;/code&gt; while testing my application. Because, with jest-cucumber, you need to specify which feature file is linked with a particular step definition file. While Codecept.js or nightwatch.js, you can write the step definition of a &lt;code&gt;given&lt;/code&gt; step in one file and the &lt;code&gt;when&lt;/code&gt; step of the same scenario in some other file. You might lose this kind of freedom if you are using jest-cucumber.&lt;/p&gt;

&lt;p&gt;That's it for now. If you want to learn more about jest and it's commands, you can refer to &lt;a href="https://jestjs.io/docs/en/api"&gt;jestjs.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hope you enjoy jesting.&lt;br&gt;
ThankYou!&lt;/p&gt;

</description>
      <category>testing</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Setup Nightwatch and run your first test</title>
      <dc:creator>Talank</dc:creator>
      <pubDate>Tue, 18 Feb 2020 05:50:28 +0000</pubDate>
      <link>https://forem.com/jankaritech/setup-nightwatch-and-run-your-first-test-o7o</link>
      <guid>https://forem.com/jankaritech/setup-nightwatch-and-run-your-first-test-o7o</guid>
      <description>&lt;p&gt;&lt;code&gt;Nightwatch.js&lt;/code&gt; is an open-source automated testing framework that aims at providing complete E2E (end to end) solutions to automate testing with &lt;code&gt;Selenium Javascript&lt;/code&gt; for web-based applications, browser applications, and websites. It is written in &lt;code&gt;Node.js&lt;/code&gt; and uses the &lt;code&gt;W3C WebDriver API&lt;/code&gt; (formerly Selenium WebDriver) for interacting with various browsers.&lt;/p&gt;

&lt;h1&gt;
  
  
  Installation And Requirements
&lt;/h1&gt;

&lt;p&gt;This guide is based on Ubuntu 18.04. Some commands will be different if you have another OS installed on your computer. Also, we will be following the BDD approach in this blog. So, if you want to learn more about BDD first then please read our blog on &lt;a href="https://dev.to/jankaritech/demonstrating-bdd-behavior-driven-development-in-go-1eci"&gt;Demonstrating BDD (Behavior-driven development) in Go&lt;/a&gt;. Before getting started with Nightwatch we need to have the following installed on our computer.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Node.js:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;To install Node.js:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install nodejs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;To verify the successful installation of nodejs and to check its version use the following command
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nodejs -v
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Node Package Manager(npm):
&lt;/h3&gt;

&lt;p&gt;The nodejs package contains both the node and npm binaries. So, npm is also installed when you run the command to install nodejs. However, to verify that npm was also successfully installed, you can check the version of npm by running the command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm -v
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Java:
&lt;/h3&gt;

&lt;p&gt;We need java to run the Selenium server which automates our browser. If your machine does not have java installed then install it using the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install default-jdk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you want to learn more about how to install Java, then you can follow this &lt;a href="https://linuxize.com/post/install-java-on-ubuntu-18-04/"&gt;link&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.Selenium Server:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://selenium.dev/downloads/"&gt;Download&lt;/a&gt; the latest stable version of the Selenium standalone server JAR file.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.Chrome Driver:
&lt;/h3&gt;

&lt;p&gt;Lastly, &lt;a href="https://chromedriver.chromium.org/"&gt;download&lt;/a&gt; the &lt;code&gt;latest stable version&lt;/code&gt; of &lt;code&gt;Chrome Driver&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once you have downloaded &lt;code&gt;Chrome Driver&lt;/code&gt;, you need to unzip it by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;unzip chromedriver_linux64.zip
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once you have unzipped it, you need to move the chromedriver(shared library) and place it inside the &lt;u&gt;same folder&lt;/u&gt; where you have placed the Selenium standalone server file.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setting up Nightwatch.js
&lt;/h1&gt;

&lt;p&gt;Make a configuration file and name it &lt;code&gt;nightwatch.conf.js&lt;/code&gt; inside the root directory of your project and inside the configuration file add the following content.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&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="na"&gt;src_folders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;test_settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;selenium_host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;127.0.0.1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;launch_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
            &lt;span class="na"&gt;desiredCapabilities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;browserName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chrome&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;javascriptEnabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;chromeOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;disable-gpu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                    &lt;span class="na"&gt;w3c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="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;You can also make a &lt;code&gt;nightwatch.json&lt;/code&gt; configuration file as an alternative to the nightwatch.conf.js file. Please refer to the &lt;a href="https://nightwatchjs.org/gettingstarted/configuration/#nightwatch-json"&gt;nightwatch website&lt;/a&gt; to learn how to write the nightwatch.json configuration file.&lt;/p&gt;

&lt;p&gt;You need to define &lt;code&gt;src_folders&lt;/code&gt; and &lt;code&gt;launch_url&lt;/code&gt; inside the nightwatch.conf.js where &lt;code&gt;src_folders&lt;/code&gt; is used to define the folder in which you have written your tests and &lt;code&gt;launch_url&lt;/code&gt; is used to define the index URL of your project which is used as the main URL to load and run your tests.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src_folders&lt;/code&gt; and &lt;code&gt;launch_url&lt;/code&gt; will be different for different projects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;src_folders:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;YOUR_SOURCE_FOLDER_FOR_TEST_FILES&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;launch_url:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;URL_OF_YOUR_WEBSITE&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Run this command to install nightwatch and cucumber into your project dependencies which allow us to run automated tests using the gherkin language.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add --dev nightwatch-api nightwatch cucumber
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Or,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --dev nightwatch-api nightwatch cucumber
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now the following information should be added inside package.json in devDependencies. But do remember that these versions may also vary depending upon the releases of these dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"devDependencies"&lt;/span&gt;&lt;span class="p"&gt;:&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="nl"&gt;"cucumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^6.0.5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"nightwatch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^1.3.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"nightwatch-api"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^3.0.1"&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;You can use npm or yarn, whichever you prefer. However, if you want to use yarn but do not have it already installed then, you can install it by downloading the &lt;code&gt;.deb&lt;/code&gt; file from the &lt;a href="https://github.com/yarnpkg/yarn/releases"&gt;yarn releases&lt;/a&gt; and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt; sudo dpkg -i yarn[VERSION].deb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The .deb file might not be compatible with your machine. It only works for debian based linux distros.&lt;/p&gt;

&lt;p&gt;For the rest of the setup process, I am using &lt;code&gt;npm&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, create &lt;code&gt;index.js&lt;/code&gt; inside &lt;code&gt;[root_dir]/test/acceptance&lt;/code&gt; and add&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;setDefaultTimeout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;After&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Before&lt;/span&gt; &lt;span class="p"&gt;}&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cucumber&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createSession&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;closeSession&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;startWebDriver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stopWebDriver&lt;/span&gt; &lt;span class="p"&gt;}&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nightwatch-api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;setDefaultTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;60000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;Before&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;startWebDriver&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;createSession&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;After&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;closeSession&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stopWebDriver&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;Here, we are using before() and after() hooks which will allow us to execute the code inside them before and after each test scenario.&lt;/p&gt;

&lt;p&gt;Before starting the Selenium server you need to change your directory to where the selenium and chromedriver files are. After doing that you can now start the Selenium server with the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;java -jar selenium-server-standalone-3.141.59.jar -port 4444
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Testing your Project
&lt;/h1&gt;

&lt;p&gt;Create feature files inside &lt;code&gt;[root_dir]/test/acceptance/features&lt;/code&gt; with an extension &lt;code&gt;.feature&lt;/code&gt; for each feature of your project. Follow the &lt;a href="https://cucumber.io/docs/gherkin/reference/"&gt;Gherkin reference&lt;/a&gt; to write your feature file.&lt;/p&gt;

&lt;p&gt;We do not need to use gherkin language but I am using it because this is the same language that user and domain experts use while they talk about the domain. Also, it is easy to understand for both technical and non-technical personnel involved in the project.&lt;/p&gt;

&lt;p&gt;A feature file written using gherkin language looks like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight gherkin"&gt;&lt;code&gt;&lt;span class="kd"&gt;Feature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; search using transliterated Latin characters
  As a user
  I want to find the literature by specifying Latin (English-style) script equivalent to the Nepali
  So I can find the literature without needing to use a Nepali keyboard

  &lt;span class="kn"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;Given &lt;/span&gt;the user has browsed to the homepage

  &lt;span class="kn"&gt;Scenario&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; user should be able to search in English characters using transliterated text
    &lt;span class="nf"&gt;When &lt;/span&gt;the user enters the English characters &lt;span class="s"&gt;"munaa madan"&lt;/span&gt;
    &lt;span class="nf"&gt;And &lt;/span&gt;the user selects the transliterated text
    &lt;span class="nf"&gt;And &lt;/span&gt;the user searches for the literature
    &lt;span class="nf"&gt;Then &lt;/span&gt;the search result should be displayed
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, create a javascript file for the step-definitions inside &lt;code&gt;[root_dir]/test/acceptance/stepDefinitions&lt;/code&gt; for each feature. For each step in the scenario of your feature file, a matching step definition is executed while running the test. Step definitions for the above search feature will look something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&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="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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cucumber&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="p"&gt;}&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nightwatch-api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;searchField&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;//input[contains(@class, 'SearchBox')]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;searchButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;//button[contains(@class,'SearchBox__Button')]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;searchResultFoundContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.sk-hits&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;searchResultNotFoundContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.sk-no-hits&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userEntersTheEnglishOrNepaliCharacters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useXpath&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;waitForElementVisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchField&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchField&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useCss&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userSearchesForTheLiterature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useXpath&lt;/span&gt;&lt;span class="p"&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="nx"&gt;searchButton&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useCss&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;the user has entered the English/Nepali characters {string}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userEntersTheEnglishOrNepaliCharacters&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;the user enters the English/Nepali characters {string}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userEntersTheEnglishOrNepaliCharacters&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;the user has searched for the literature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userSearchesForTheLiterature&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;the user searches for the literature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userSearchesForTheLiterature&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;the search result should be displayed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;waitForElementVisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchResultFoundContainer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;waitForElementNotPresent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchResultNotFoundContainer&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;the search result should not be displayed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;waitForElementVisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchResultNotFoundContainer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;waitForElementNotPresent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchResultFoundContainer&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, run the test from the root directory using the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cucumber-js --require test/acceptance/index.js --require test/acceptance/stepDefinitions test/acceptance/features/[YOUR_FEATURE_FILE].feature 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Does the above command look long? I am sorry, but you have to use that command every time you run the test. But only the name of &lt;code&gt;your feature file&lt;/code&gt; is different, while running different tests, the rest is all the same. So, let's assign an easy short name for the rest and put it inside the scripts section of &lt;code&gt;package.json&lt;/code&gt;. I called it &lt;code&gt;test-e2e&lt;/code&gt; and inside the scripts of &lt;code&gt;package.json&lt;/code&gt;, I added&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"test-e2e"&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="s2"&gt;"cucumber-js --require test/acceptance/index.js --require test/acceptance/stepDefinitions"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, the above long command is shortened to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run test-e2e test/acceptance/features/[YOUR_FEATURE_FILE].feature
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That's it. Now, you are ready to run test suites for your project. You can refer to &lt;a href="https://nightwatchjs.org/"&gt;Nightwatch&lt;/a&gt; to read more about Nightwatch and its commands. &lt;/p&gt;

&lt;p&gt;Hope you enjoy testing.&lt;br&gt;
ThankYou!&lt;/p&gt;

</description>
      <category>testing</category>
      <category>javascript</category>
      <category>nightwatchjs</category>
      <category>selenium</category>
    </item>
  </channel>
</rss>
