Posted on Leave a comment

QA Bite ::: Don’t Delete Flaky Tests

In many teams, I see that there is a strong emphasis on deterministic tests: Each test must pass every time if there is no change in the code base. Wayne Roseberry from Microsoft shows that this is not helpful:

Especially the tests which pass only 60-90% of the time contributed to many bug reports in his projects. Unreliable tests are not easy to use in build pipelines. Gating tests must be fast and precise. But, in nightly test runs, test teams benefit from flaky tests during bug discovery.

Posted on Leave a comment

QA Bite ::: Create a Test Plan in 10 Minutes

For those who need to implement tests from scratch there is a great idea how to start: A create a Test Plan in 10 minutes. This idea was written down by James Whittaker, a former Google Test Director [The 10 Minute Test Plan].

The idea is to first derive Attributes for the Application and its User Experience (Fast, Easy to use, Secure, Rich content). Then, we need to define the Components like Search bar, Filtering or Geolocation. An finally, we use verbs for the Capabilities of the user, e.g. Save to favorites, Make payments, Write and read reviews.

These Capabilities are the starting point for user stories and test cases.

This approach actually takes a little longer than just 10 minutes, but it delivers most of the functionality in minimal time.

Create Test Case

Summary:

#1 Check response when the logged user clicks “Book”

Test steps:

  1. Go to the hotel page
  2. Click Book

Conditions:

  • Log in via test user ID
  • ID: test
  • Password: test123

Expected Result:

A user goes to the payment page

Posted on Leave a comment

QA Bite ::: Test the Payment Flow of your Shop

Testing E-Commerce websites regularly, I often get asked how to test the purchase flow. This is a delicate topic: It is vital for any shop owner that the purchase and payment flow of the shop runs smoothly. But, it involves real money – something alien to QA testing.

So, these are your options:

  1. Create a coupon for 100% discount and use this coupon in your test. 
  2. Enable Invoice Payment (e.g. WooCommerce->Settings->Checkout->Cash on delivery).
  3. Use a stage environment and set your payment provider to sandbox mode (e.g. Paypal or Stripe).
  4. Use a real credit card during purchase flow. Refund after the test. This usually leaves you with remaining fees from the payment provider and can hurt your credit score. Make sure to use a separate card and talk to the payment provider that your refunds are part of tests.

Using the first two options, you can test many important steps of your purchase flow, except the payment itself. This is sufficient in most cases. Note:Make sure that the goods purchased are not sent out 🙂 

If you already have a stage environment, option 3. is best. It tests much of the communication with the payment provider. Then, you can go to the payment provider’s website and check if the communication was correct, too.

The real test is option 4. With real money, you can do real testing of production shops. If you have a shop with low volume and your last payment was a few days ago, test using option 4 manually and verify that it’s not a technical issue.

Posted on Leave a comment

QA Bite ::: Improve Team Communication: Write Tests First

An excellent way to communicate defects or new user stories in the development process is to write tests first. Testup looks at the software the same way as a user would do. Therefore, it is easy to describe what the user should see and experience. 

Create a test that goes to the screen in question. Then, use Tags to describe what the user should see. This way, the Product Owner can easily define the screen that needs to change and the Developer knows what to do. 

In your Ticket system, simply create a ticket for the issue and link the test case URL (something like https://app.testup.io/testcase/1234567) you find in your Browser.

An additional benefit is that the developer can add the new functionality to the Test and hand back the test to the Product Owner for acceptance testing.

Posted on Leave a comment

QA Bite ::: Use Robotic Process Automation to Migrate Data from Old Systems

If you are in business for a couple of years, you will know about this issue: You introduce a new software to replace an old system. Now, you need to export the data of the old system and import it to the new one. Easy. But, what if there is no import or export functionality of the data you need? Create a Testup test as a robot which does it for you:

Posted on Leave a comment

QA Bite ::: Use Data to Drive your Tests

I often have the issue that I need to check the same website with different input values. Last time I wanted to check if different product categories in a web shop are displayed properly in the shopping cart. The solution is to use a Google Spreadsheet which contains the different products.

  1. Create a Google Spreadsheet and enter the data you need.
  2. Share the sheet with a link such that everybody with a link is a viewer.

In you shop test, insert the action NAVIGATE_URL and Paste the link of the Google Sheet into this action and play:

  • Use arrow keys on your keyboard to navigate to the first item of the sheet
  • Use <copy> from <Control> group to copy the data to the clipboard
  • Use NAVIGATE_NEXT_TAB to get back to your shop
  • Paste data into the shop
  • Add steps to verify the Shop is ok.
Posted on Leave a comment

How to Preserve Cookies / Localstorage Session across Tests in Cypress

Cypress clears localStorage between tests by default, which can be a concern if you’re testing out features that use localStorage. However, there is a Cypress package that lets you preserve your localStorage data across tests. Using the cypress-localstorage-commands plugin, you may utilize all browser localStorage methods through Cypress commands, and it will be saved between tests. It can also be used to make it appear as if localStorage is disabled in the browser. Follow the steps below to enable Cypress to preserve localStorage sessions across tests.

Step 1: Installation

The cypress package is distributed via npm which is bundled with node and can be installed as one of your project’s devDependencies by typing the following lines of code in your console:

npm i --save-dev cypress-localstorage-commands

Step 2: Usage

To use the Cypress localStorage package after installation, you need to import it into your projects by adding the following line of code to your cypress/support/commands.js file:

import "cypress-localstorage-commands"

Step 3: Using the commands

Now that you have rightly installed and imported the package, you can now use the following commands to use Cypress to interact with localStorage:

cy.saveLocalStorage(): Enables current localStorage values to be saved in an internal “snapshot.”

cy.restoreLocalStorage(): Causes localStorage to be restored to its previous “snapshot” saved values.

cy.clearLocalStorageSnapshot(): Clears the “snapshot” values in localStorage, cleaning out previously recorded data.

cy.getLocalStorage(item): Gets the item from the localStorage. It is the same as localStorage.getItem in Javascript. Item is the data we would like to retrieve from the localStorage.

cy.setLocalStorage(item, value): Sets the value of the localStorage item. It’s the same as localStorage.setItem in Javascript. The item parameter is the name we would like to use to store the value in localStorage while value is the data we would like to save in localStorage.

cy.removeLocalStorage(item): Deletes an item from localStorage where item refers to the name of the item to be removed.

cy.disableLocalStorage(options): This disables localStorage. It produces localStorage methods to throw errors.

Here is an Example

Suppose we would like to test an “Add To Cart” button of an eCommerce website that saves the data of the shopper to localStorage, we can perform this test by writing the following lines of code:

describe("Add to cart button", () => {
  const ADD_TO_CART_BUTTON = "#save-user-data";

  before(() => {
    cy.clearLocalStorageSnapshot();
  });

  beforeEach(() => {
    cy.restoreLocalStorage();
    cy.visit("/");
  });

  afterEach(() => {

    cy.saveLocalStorage();
  });

  it("should be visible", () => {
    cy.get(ADD_TO_CART_BUTTON).should("be.visible");
  });

  it("should not be visible after clicked", () => {
    cy.get(ADD_TO_CART_BUTTON).click();
    cy.get(ADD_TO_CART_BUTTON).should("not.be.visible");
  });

  it("should not be visible after reloading", () => {
    cy.get(ADD_TO_CART_BUTTON).should("not.be.visible");
  });
});