Categories
Life

Bye Bye Bear 🐻

Science is organized knowledge; wisdom is organized life.

—Immanuel Kant.

I’m a big fan of taking notes to organise my work and life, and I’ve been using Bear as a notetaking app over the last few years* (coming across from Evernote). I like it for its simplicity but it seems like this simplicity has become its Achilles’ heel.

I started using a separate Apple ID for my work and the issue with Bear is it’s macOS and iOS only and it uses iCloud sync so I can’t use it on my work laptop which uses a separate Apple ID – there is a plan to have a web version of Bear at some point but the intention has been talked about for years but nothing has happened.

At some point you give up on what you love and find something that works for you. I’ve been using Zoho Notebook for a few weeks now and I like it. It does tables (which bear doesn’t support) and I like how it arranges notes (or cards as it calls it) into separate notebooks reflecting real life. There’s clients for macOS and iOS (which don’t use iCloud for syncing) and also a web version for use anywhere anytime. It seems to suit my purposes well and it’s free (supported by development of other Zoho products).

My notebooks look like this:

What do you use to organise your work/life/notes?


*We also use a Simplenote account logged into multiple iDevices to share text snippets/to do lists for our household.

Categories
macOS

Homebrew on macOS Big Sur

I recently upgraded to macOS 13 Big Sur and found homebrew wouldn’t work.

I worked out you need new XCode command line tools:

sudo rm -rf /Library/Developer/CommandLineTools
sudo xcode-select --install
brew update
brew doctor
brew upgrade

This worked a treat – now brewing on Big Sur 🥸

Categories
Aside Software Testing

Quality Advocates

“What I’m seeing more and more of, is the test-always, or test-as-quality-accelerant  – or maybe, with a nod to Atlassian, the quality-assistance school. In more and more teams, testers are taking on the role of quality assistant, quality coach, or quality experts. Rather than existing in a separate team, they are members of feature teams and take on the responsibility for ensuring that the entire team embraces a quality culture. Yes, they absolutely bring testing expertise to their product or feature area, and they test the product more than anyone else on the team; but they also help other developers write and improve their own testing and think a lot about the customer experience. Good developers are extremely capable of writing tests (including service monitoring and diagnostic tools) for their own code, but testing experts ensure that the end-to-end experience and other big picture items (e.g. load or perf) are covered as part of the daily work.

Teams with testers like these typically do not have a release phase since they are (typically) releasing often or always.”

Alan Page – April 2017 #

Many years later I still think a small development team with a product owner and a single strong tester/quality advocate/paradev is the best way to produce software consistently and predictably.


Categories
API Testing Automated Testing

API “approval” testing using Jest

I recently added some API integration testing examples to my Playwright/Jest e2e automated testing repository using Supertest.

I wanted to also explore the use of Jest for approval testing of REST JSON APIs.

Jest has in built support for snapshot testing which is most commonly used to test how React components are rendered – however Jest snapshot testing can also be used to test any serializable values.

Snapshot tests are an example of what are are also known as approval tests: whereby the expected output of a test is generated the first time it is run and compared against this on subsequent runs. Changes to the output can be “approved” which become the new baseline.

These are no where near as common as “assertion” based tests whereby an automated test performs some action and asserts some results.

Assertion tests can be used to assist test driven development, whereas approval tests are generated after the fact so they can be useful for outside-in software development, API integration testing of known endpoints, and for legacy code where no assertion based or lower level tests exist.

I wrote the same integration tests in both approval and assertion style to show how these differ.

Say we have an endpoint that returns all the blog posts we have seeded into our system, we could write some assertions on the content:

const response = await request.get('/posts')
expect(response.status).toBe(200)
expect(response.body.length).toBe(3)
expect(response.body[0].id).toBe(1)
expect(response.body[0].title).toBe('Post 1')
expect(response.body[1].id).toBe(2)
expect(response.body[1].title).toBe('Post 2')
expect(response.body[2].id).toBe(3)
expect(response.body[2].title).toBe('Post 3')

Since we’re testing an existing endpoint with known “approved” behaviour we can generate and test a snapshot of it:

  const response = await request.get('/posts')
  expect(response.status).toBe(200)
  expect(response.body).toMatchSnapshot()

The first time we run this the following is generated in a separate file:

// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`can GET a REST API and check response using approval style 1`] = `
Array [
  Object {
    "id": 1,
    "title": "Post 1",
  },
  Object {
    "id": 2,
    "title": "Post 2",
  },
  Object {
    "id": 3,
    "title": "Post 3",
  },
]
`;

We commit this to our codebase and if any of the body returned for this endpoint is changed our test fails (with an option to approve the new result as the new baseline).

The benefit of these approval tests is they are quicker to write for an existing endpoint (since they are generated automatically) and are complete in that any change to the body returned will be highlighted – compared to our assertion based tests which only test specific things.

The downside to these tests is they are generated after the fact – so aren’t compatible with test driven development – and need to take into account if there is any dynamic content that changes between test runs – so these generally aren’t good for non-deterministic systems.

Feel free to check out the source code for these API integration tests and let me know what you think and whether you’ve had experience, good or bad, with approval testing.

Categories
e2e Testing

Playwright + Jest = 💖

We were looking at a possible replacement for our dated Protractor + Cucumber e2e testing framework. As we move away from Angular to React microapps we have found that Protractor doesn’t work very well/efficiently and cucumber isn’t giving us any benefits.

It was a good opportunity to do some research/tinkering to answer the question lingering in my mind: in 2020 what e2e testing tool would I use by default for a dynamic react based web application?

After some experimentation it came down to Puppeteer + Jest or Playwright + Jest. I’ll compare those in this post.

Why Jest?

As explained previously we don’t need a BDD framework, but we do need something that allows us to specify our tests, create assertions and run these tests (in parallel). Jest, particularly when using the Jest Circus test runner, seems the most mature tool in this regard in 2020. Whilst Jest is often associated with React as it handles the snapshot test results also, it doesn’t need to be used with React and it’s possible and easy to use it as a standalone Node.js testing library.

Parallel Support

Jest by default runs tests across files in parallel and uses the available resources to scale appropriately using processes/threads. I’ve found this particularly good as I write independent e2e tests which can scale through parallelism, and using Puppeteer and Playwright you can spawn new incognito browser contexts to run these.

Auto-Retry Support

Whilst I believe in writing deterministic e2e automated tests, since e2e tests are full-stack there are often external dependencies and services beyond our control (like a third party domain provider) and I’d rather prioritize test reliability over test perfection. With this mind I think it’s important to be able to automatically retry a single failing test scenario before failing a build, and the Jest Circus test runner supports this:

jest.retryTimes(1)

test('can wait for an element to appear', async () => {
  global.page = await pages.spawnPage()
  await nav.visitHomePage(global.page)
  await global.page.waitForSelector('#elementappearschild', { visible: true, timeout: 5000 })
}, jestTimeoutMS)

HTML Reports and Screenshots

Nice looking HTML reports are easy to achieve by using jest-stare and screenshots are easy to generate using Jest Circus hooks.

Playwright or Puppeteer?

I’m a fan of Puppeteer however Playwright is a much nicer browser automation library. Whilst it adds support for Firefox and Webkit, even if you’re running your e2e tests in one browser (Chromium) I’d still recommend Playwright over Puppeteer any day of the week. Here’s why:

Automatic Waiting

I’ve found the automatic waiting in Playwright just works™️ Especially when dealing with dynamically rendered react web apps I’ve found my Puppeteer code looks is full of page.waitFor calls to make it run reliably:

await page.waitFor('#loadedchild', { visible: true, timeout: 5000 })

Whilst this is occasionally necessary in Playwright (in particular waiting for an iFrame to switch into), I’ve found it’s almost never required which reminds me of good old Watir days.

Nicer API

Whilst the APIs are similar, Playwright is just nicer to use. Take grabbing some text from a div, in Puppeteer:

await page.goto(`${config.get('baseURL')}`)
await page.waitFor('#loadedchild', { visible: true, timeout: 5000 })
const element = await page.$('#loadedchild')
const text = await (await element.getProperty('textContent')).jsonValue()
expect(text).toBe('Loaded!')

In Playwright:

await page.goto(`${config.get('baseURL')}`)
const text = await page.textContent('#loadedchild')
expect(text).toBe('Loaded!')

Summary

If I was writing an e2e web testing framework from scratch in 2020 I would use Playwright + Jest. Playwright offers automatic waiting and a nice API, whilst Jest offers a solid runner with parallel support, automatic retries and the ability to easily generate HTML reports and capture screenshots.

I’ve created one repository for Playwright + Jest #
And another for Puppeteer + Jest to compare #

As an aside we put changing node libraries on hold for our e2e test framework and will look at some test infrastructure improvements instead.

Categories
e2e Testing

Puppeteer Jest Demo

I’m trying to work out what would be the ideal combination for an e2e web testing framework in Node.

I wanted to try Jest with Puppeteer (I’d previously used Mocha) and I also wanted to try avoiding Babel for transpiling and using JavaScript directly so I came up with this example on GitHub.

I think I’ll try using TypeScript for my next tinker project.

Categories
Remote Work

Corner Office?

I read and enjoyed this article by Jim Grey: Too soon to declare victory on distributed work

“A group of voices in our industry has said for years that we would all be more productive and have a superior work-life balance if we all worked from home. Now that we’re all working from home and it’s basically working, they are crowing victory.”

Jim Grey

The article linked is to is a NY Times article, ironically printed on paper, of an interview with the CEO of the digital publishing company where I worked remotely for over three years.

“This column is called Corner Office, and most people who choose to have offices are usually the bosses. And I’ve been to the offices of billionaire C.E.O.s that have their own private bathroom, beautiful art and couches. But these are all things that you can have in your house. What I love about distributed organizations is every single employee can have a corner office.”

Matt Mullenweg via the NY Times # (emphasis added)

What Mullenweg doesn’t state is that this is a rich person’s view of distributed work. What isn’t mentioned is the cost of having a dedicated “corner” office in your home, a private bathroom, the cost of beautiful art and couches (and no Automattic wouldn’t reimburse art, nor couches, nor home renovations, only a monitor/desk/chair, at least during my time there).

I wrote about this aspect of remote work in my essay:

“Housing costs are very high in Australia and we’re moving to smaller and more expensive houses so it’s increasingly harder to justify having a dedicated office at home. If you were building a house to live in here in Australia adding a 15-20 square meter dedicated home office for remote work could easily add $30,000-$40,000 to your build costs.”

The future of work? An essay.

As a single-income family-of-five our rented home is much smaller, more humble and basic than the office our company leases. Even as an individual contributor at work I can sit and eat my lunch, or wander around with views like these:

Our office view – accessible to all employees

Another interesting angle on having an office space available to all staff is that it makes a safe, comfortable and productive work environment available to everyone regardless of personal circumstance.

I wrote about this in my essay also:

“If you don’t have a suitable place to work from home, and co-working expenses are too expensive, or not available or too far from home, this means that there’s a whole group of people who can’t consider remote work which reduces the diversity of the workforce.”

The future of work? An essay.

This concept was recently mentioned in an article in Australia about a tragic domestic violence case:

“Ms Foster says for many people experiencing violence their workplace has been a sanctuary — somewhere they can escape “the horrors they’re experiencing at home”.

She says women working from home have been sharing with her how they are being constantly harassed, threatened, and assaulted, only to have to then join a video conference and act professional.”

Sam’s mum was killed while working from home. He hopes his workers compensation win will help others facing family violence #

Conclusion

I still think it’s naive, borderline dangerous, to crow victory on working from home as a one-size-fits-all solution to the world’s problems – and pretend that every person in the world can afford to have their own “corner office” in their home, when for a lot of people, a working environment for work can be a better or only option to work safely and productively.

Categories
Agile Software Dev

Rapid feature delivery using “Fast Follows”

I’ve mentioned previously that I like using “Now”, “Next”, “Later”, “Never” as a way to prioritise the system features we’re delivering.

But we often get in a situation where we want to deliver a “now feature” quickly, but we find something that we need to do on it that we don’t want to want to group with the “next” features. To steal a term startups use and reinterpret it: we call these “Fast Follows”.

“Fast Follow” is a startup strategy that aims to build a company by copying an already proven business model- and executing quickly to “follow” the moves of the predecesor.

https://worldaccordingtocarp.wordpress.com/2010/01/21/the-fast-follow/

Fast follows allow us to quickly ship “now” features into the hands of our customers knowing we have a mechanism to follow quickly with an enhancement or bug fix.

Do you do “fast follows”? What do you call them?

Categories
Remote Work

Back in the office

I’ve been back in the office for a few weeks now. Only about 10% of our company can work in the office and even then only about that percentage are keen to return (at present).

I find myself enjoying work again and regaining the ability to mentally separate work from home has been energizing me for when I am at work. Also having people around motivates and recharges me at work.

I read an interesting article written by Justin Qin, a year 8 high school student, who reflects on returning to school after many weeks of home-based learning:

“Lockdown and home schooling had been a lonely environment for me — even with two energetic brothers for company, and Instagram on repeat.

And after days at a time like this my friends and I chatted constantly when we saw each other, flushing out the loneliness of isolation and reviving the joy of face-to-face chat even though we had to maintain that all-important distance.

Being in the classroom, and the ease of talking to my teacher and other students, makes school a place where I can actually learn and be engaged.

My school day was spent stuck at a desk at home, with tiny breaks and no time to chat to friends as we transitioned between lessons. I often felt as if I had not stood up for hours at a time.

The result was that learning from home was seriously affecting my physical and mental health.

Mentally, I wrestled with finding the meaning of my life when so much of it was spent alone at a desk.

Physically, I ate significantly less food than normal.

With these struggles I cannot see a strong future for online classes replacing school.”

Justin Qin on returning to Year 8 at School #

When I look at my LinkedIn feed it’s full of articles, comments and observations that many people can’t see themselves returning to the office in the near, or far, future.

I put this down to one of two possible things:

  1. People are still in the “honeymoon” period of full time working from home; and/or
  2. People are confusing working from home with having flexible working conditions

“The first six months were a dreamlike period, where everything you’d ever hated about office life – underlings, overlords, sharing bathrooms with people who you’re thankful aren’t your family – morphed into amusing memories.”

“It’s all fun and games at first, a novelty, the home work thing, and being close to your own fridge is great, but the slow evaporation of the mental distance between your home life and your work one is an insidious one.”

Stephen Corby : You might love working from home now, but give it a year

As I’ve stated previously, I personally don’t find myself healthy, happy or productive working from where I live. I prefer to separate work and home, and to have people I’m working with around in real life.

But I’ve also said we need more flexibility in the way we work, working from home doesn’t have to be the only way we can have flexible working conditions.

I’ve also seen a somewhat disturbing trend to encourage everyone to act like they’re working remotely even if they’re in the office:

“If everyone sits at their desk on an individual video call screen, the playing field is equal. Everyone’s faces are easily distinguishable, it’s easy to know whose turn it is to talk, and it simply puts everyone’s input on equal footing.”

6 Rules To Live By When You Work In An Office But Have Remote Team Members

I’ve tried doing that and the audio feedback from having someone sitting near you talking on the call and also near you is terrible, it’s loud and distracting for other’s in an open plan office, and it feels weird to pretend we’re not in the office when we are.

Conclusion

I still think it’s too early to declare that ever working from an office again is not going to happen. As I have previously stated – it’s been good to show employers that employees can still be productive when given workplace flexibility – however I think there will be recognition that working 100% in physical isolation from colleagues isn’t necessarily a good thing.

“A world in which people who want to can do a bit of both, working home alone some of the week and sharing an office with other humans the rest of the time, might just be the perfect balance, for those lucky enough to swing it”

Stephen Corby : You might love working from home now, but give it a year

Categories
Specification by Example

Given/When/Then with Style?

Gojko Adzic has started a series of challenges on the Specflow blog where readers can submit solutions to common problems writing automated tests using gherkin (Given/When/Then).

The first challenge is:

“What’s the best way to describe a Given for a value that’s not supposed to be there? For example, starting the specification from a point of a user who does not yet exist in a database, or a product that’s not been set up. “Given a user that doesn’t exist” sounds vague, but “Given user John that does not exist” sounds silly – how can we talk about John if he doesn’t exist yet?”


Gojko Adzic
Given user John does not exist
When John tries to register
Then the registration is successful

Given user John exists
When John tries to register
Then the registration fails

How would you improve the scenario of our example to solve the challenge of this week?

Gojko Adzic

Interestingly this problem highlights the issues I found using Gherkin to specify business rules and examples I previously wrote about:

“I’m not keen on writing specifications in gherkin (Given/When/Then) as I think it’s too generic and frequently makes the feature specifications too verbose – and takes emphasis away from the critical parts.”

Example of lightweight feature documentation

I prefer bullet points and tables.

I’d specify the above scenarios as follows.


User Registration

Rules

  1. A user can only register a single account per unique email address
  2. A user’s email address is their username
  3. A user can register using their Google or Facebook account without having to enter a username or password
  4. A user must enter a password unless they are registering using Google or Facebook
  5. Passwords must contain at least 4 letters and 4 digits
  6. Passwords are maximum length of 10 and can contain any ASCII characters

Registration Scenarios/Examples

ScenarioExample Email AddressResult
New user signs up with a new email new.customer@hotmail.com✅ Registration Successful
New user signs up with a new email and invalid password new.customer@hotmail.com❌ Registration Unsuccessful – Validation Error Displayed and no account created
User attempts to sign up with email already registered email for account with password existing.customer@hotmail.com❌ Registration Unsuccessful – Reset password page displayed with email prefilled
User attempts to sign up with email already registered email for account with Google log-inexisting.customer@gmail.com❌ Registration Unsuccessful – Log in with Google page displayed

It’s tempting to put passwords into the above table, which is what I originally did, but I’ve found it’s better to specify those separately (in the same document).


Passwords Scenarios/Examples

Password ScenarioExample PasswordValid/Invalid
Less than 8 characters123
Less than 4 digitsaaaabbbb
Less than 4 letters123456aa
No emoji – ASCII Chars Only1234abcd💀
More than 10 characters123456abcdef
10 Characters with ASCII1234abcd%$
4 digits and 4 lettersabcd1234
Special characters don’t count as lettersabc$1234

Summary

Whilst these scenarios aren’t gherkin I don’t think they need to be. They could be taken by developers and written as unit tests alongside the code. I wouldn’t have an e2e automated test that tests this logic at this level – it’s complex and an expensive waste of time.

I’ll be interested to see the follow up posts about the best way to specify these in gherkin, as I can’t see a clearer way than just using bullet points and tables 🙌