davidkpiano / xstate-test-demo

Demo React project for model-based testing with @xstate/test
112 stars 33 forks source link

Reuse functional state machine, or create separate version for tests? #8

Open ooloth opened 4 years ago

ooloth commented 4 years ago

I'm excited to give this a try!

My app logic is implemented using a state machine. I now want to generate tests for that machine using @xstate/test.

For the machine I'll feed to createModel, which of the following approaches is the right idea?

  1. Add my assertions to the existing state machine
  2. Create a duplicate state machine with the same states and transitions but without other implementation details (e.g. actions, services, etc) and add my assertions to that machine
  3. A combination of (1) and (2) or something else I'm not thinking of 🙃

(Thanks!)

rjdestigter commented 4 years ago

For machines that drive application logic I tend to export machine configuration and machine options separately:

import { createMachine as createXStateMachine  } from 'xstate'

export const configuration = { .. }
export const actions = { .. }
export const services = { .. }
..
export const createMachine = createXStateMachine(configuration, { actions, services })

This allows me to import the pieces in my test file and enhance the configuration's states with meta.test

CodingDive commented 4 years ago

@rjdestigter so that sometimes you can decide to mock the services, actions, etc. or do you leave the machine config mostly unchanged in the test?

rjdestigter commented 4 years ago

@CodingDive Yeah exactly

baeharam commented 3 years ago

@rjdestigter I understood your code and intention, but machine options(such as actions, services, guards) have to be separated from machine to implement test without duplicating existing machine. It makes lots of boilerplate codes and this problem is worse in TS than JS. I think it should be possible to use existing machine without separating machine options. How do you think?

rjdestigter commented 3 years ago

@baeharam David has recently added a guide on testing state machines that might help you: https://xstate.js.org/docs/guides/testing.html

baeharam commented 3 years ago

@rjdestigter I read your link, but it still has problem. If I follow that guide, I have to test all paths generated from every states and events. To test every paths simply, I have to use @xstate/test but I have to write meta property for each state. It means test code and implementation code would be mixed. It's harmful to readability and maintainability. I think there should be more cleaner way to test every paths of machine like withMetaInfo method. cc @davidkpiano

davidkpiano commented 3 years ago

It means test code and implementation code would be mixed

It's not "test code and implementation code" - it's test code and test code. The state machine describes the flows of the system under test, with assertions (in meta.test) that make sure each visited state is actually in their expected state.

baeharam commented 3 years ago

@davidkpiano Thanks for comment! Then, it means that meta property should be included in machine ?

davidkpiano commented 3 years ago

@davidkpiano Thanks for comment! Then, it means that meta property should be included in machine ?

Not sure what you're asking, but you can put meta on the machine itself.

baeharam commented 3 years ago

@davidkpiano

Not sure what you're asking,

What I'm asking

But, your explanation is that machine is also "test"?

martypenner commented 3 years ago

@baeharam I've struggled to understand this too. It made more sense once I read this tweet. The goal is NOT to import your machine and generate tests from it. The goal is to write a NEW machine that acts like your users will, and test that. According to the xstate advice, you should not be trying to directly instrument your app's machine in the test files you create.

baeharam commented 3 years ago

@martypenner Thanks for the link! I understood intention of "model based testing". However, when machine is changed, test and machine should be changed. It means that working should be twice, isn't it? Then, is it weak point of "model based testing"? Or Is my understanding wrong?

martypenner commented 3 years ago

It depends on what the user expects. If you are making an internal change (like refactoring) that won't impact what the user sees, then you shouldn't have to change the test model.

baeharam commented 3 years ago

But, if it is not internal change which have to be exposed to user interaction, two parts(machine and test) should be changed. isn't it?

martypenner commented 3 years ago

That sounds correct to me.

baeharam commented 3 years ago

@davidkpiano Then is it weak point of this mechanism?