Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
ooloth opened this issue Nov 19, 2019 · 16 comments
Open
Labels
documentation Improvements or additions to documentation question Further information is requested

Comments

@ooloth
Copy link

ooloth commented Nov 19, 2019

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!)

@ooloth ooloth changed the title Reuse functional state machine, or write a separate version for tests? Reuse functional state machine, or create separate version for tests? Nov 19, 2019
@davidkpiano davidkpiano added documentation Improvements or additions to documentation question Further information is requested labels Nov 19, 2019
@rjdestigter
Copy link

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
Copy link

@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
Copy link

@CodingDive Yeah exactly

@baeharam
Copy link

baeharam commented Nov 5, 2020

@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
Copy link

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

@baeharam
Copy link

baeharam commented Nov 6, 2020

@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
Copy link
Owner

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
Copy link

baeharam commented Nov 9, 2020

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

@davidkpiano
Copy link
Owner

@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
Copy link

@davidkpiano

Not sure what you're asking,

What I'm asking

  • machine is "implementation"
  • meta property of machine is "test"

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

@martypenner
Copy link

@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
Copy link

baeharam commented Nov 11, 2020

@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
Copy link

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
Copy link

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
Copy link

That sounds correct to me.

@baeharam
Copy link

@davidkpiano Then is it weak point of this mechanism?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation question Further information is requested
Projects
None yet
Development

No branches or pull requests

6 participants