Hello there internet stranger, πŸ‘‹πŸ½

This is the 3rd article in the Software Engineering(SE) Log.

A little about me, I’m Alex, and I have no freaking idea what I’m doing. But, I’m taking one step at a time to learn and trying to figure things out.

Technical skills

Testing πŸŽ™

I was going for a mic check with the emoji, but uuuuhh (awkward stares)… moving on swiftly

This week was spent improving our end-to-end testing for the smoke tests. It was pretty neat because I learnt how to create a test matrix with jest. A test matrix reduces repetitive tests that uses the same data.

Let’s back up for a moment and explain some jargon.

What is a test?

A test is code that tests your code ensuring it does what it’s suppose to.

Testing may be manual – a user going through your application and finding bugs – or automated – a program runs assertions against your code to ensure everything works correctly.

There are different types of tests such as unit, integration, and end-to-end tests that help build confidence you’re not shipping any bugs – which are features sometimes. It can be painful sometimes writing tests but on the bright side, it’s a great skill to have and you ship less bugs. πŸ™‚

This Log won’t cover everything that has to do with testing because there’s a lot and it can’t be summarized into a short article. However, you can check out the Google Test User Guide. It provides a good introduction to testing concepts. It’s specific to C++ but I think it provides a good foundation in testing.

I accidentally once shipped a slightly broken feature about 2 weeks ago. It wasn’t a bug, but it didn’t behave as expected. I still haven’t fixed it but by the time this log is out, there’ll be a PR fixing it.

End-to-end tests aka smoke tests

An end-to-end (e2e) test is a test that simulates a user’s interaction in an application. I.e, it opens up the application up on an emulator (browser window or mobile emulator) and interacts with the application by clicking links, filling out forms etc.

There are a suite of tools that can be used to accomplish this such as Cypress and Playwright for web-based applications.

To give a sense of what this would be like, here’s a small guide on getting started with Playwright. It’ll use the GraphQL-Next.js Prisma example.

A small demo testing with Playwright

Set up the application

Download the example and install dependencies:

curl https://codeload.github.com/prisma/prisma-examples/tar.gz/latest | tar -xz --strip=2 prisma-examples-latest/typescript/graphql-nextjs
cd graphql-nextjs
npm install

Set up the database (this uses SQLite for ease of set up)

npx prisma migrate dev --name init    # Creates a database and applies the schema against it
npx prisma db seed --preview-feature  # Seeds the database based on `prisma/seed.ts
npm run dev                           # Starts the application server

On a separate terminal, install playwright as a devDependency:

npm install --save-dev @playwright/test
npx playwright install

It’s now time to write an example test for the application. At the root of the project, create a folder called tests and a file called test.spec.ts. In test.spec.ts, paste in the following:

import { test, expect } from '@playwright/test';

// 1
test.describe('User flow:', () => {
  // 2
  test.beforeEach(async ({ page }) => {
    await page.goto('http://localhost:3000');
  })

  // 3
  test('signup', async ({ page }) => {
    // 4
    expect(await page.getAttribute('text=Signup', 'href')).toBe('/signup');

    // 5
    await page.click('text=Signup');

    await page.fill('[placeholder="Name"]', 'John');
    await page.fill('[placeholder="Email address"]', 'john@email.io');

    await page.click('[value="Signup"]');

    expect(await page.waitForSelector('text=My Blog')).toBeTruthy();
    expect(await page.url()).toBe('http://localhost:3000/')
  })

  test('cancel signup', async ({ page }) => {
    expect(await page.getAttribute('text=Signup', 'href')).toBe('/signup');

    await page.click('text=Signup');
    await page.click('text=or Cancel')

    expect(await page.waitForSelector('text=My Blog')).toBeTruthy();
    expect(await page.url()).toBe('http://localhost:3000/#')
  })
})

The following test does a number of things:

  1. This groups logically related tests
  2. Creates a hook that executes before a test is run. In this case, it navigates to the application
  3. The test definition
  4. An assertion to verify what is expected to be on the user’s device
  5. Simulates user interaction

Run the test:

npx playwright test

The tests does the following:

Test case 1:

  1. Navigates to http://localhost:3000
  2. Clicks the Signup link
  3. Fills out the user information
  4. Submits values

Test case 2:

  1. Navigates to http://localhost:3000
  2. Clicks the Signup link
  3. Exits from the flow

The output on your terminal should resemble this:

You can make the test intentionally fail by playing around with the values in .toBe('random_value') method.

The tests run on the CLI – in headless mode, meaning there’s no browser window being opened. You can play around with the configuration.

This is just a glimpse of what e2e tests look like and there’s so much more that you can do with e2e tests.

Soft skills

Learning in public

An interesting thought I had earlier this week was on sharing knowledge or learning in public. Most of the time – especially as a beginner or even if you’re senior – you may feel like you’re not qualified enough to share the knowledge you have for a number of reasons. Maybe, you’re not good at it yet, someone else has done it or any other excuse that may come up, preventing you from talking about what you learnt.

Well, go ahead and do it!

Am I qualified to talk to you about Playwright, testing, TypeScript (the list is endless) or any other topic?

No.

Maybe.

I don’t know.

But, the more you make content about what you love, the easier it gets and someone out there will appreciate your work.

Start before you think you’re ready.

Matt D’Avella

Do what brings you joy and enjoy the process. πŸ™‚

Till next week. ✌🏽