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

How to write tests? #416

Open
StarpTech opened this issue Dec 20, 2018 · 10 comments
Open

How to write tests? #416

StarpTech opened this issue Dec 20, 2018 · 10 comments
Labels
docs high priority planned We intend to add this feature or refactor in the future.

Comments

@StarpTech
Copy link

StarpTech commented Dec 20, 2018

Hi,
I'm looking for an easy way to write tests for gluegun commands which access the toolbox (file system, process...) Does exist any test helpers? It seems that testing isn't taken seriously when I look at the referenced projects in the Readme.

@lednhatkhanh
Copy link

I'm also look for a way how to test promt commands

@kyleect
Copy link

kyleect commented Dec 21, 2018

That depends on the type of tests you are aiming for. I would assume nearly all being unit tests then toolbox can be mocked out. I believe this can be applied to extensions as well.

I just started looking in to this as well so I'll post anything I find.

@StarpTech
Copy link
Author

StarpTech commented Dec 21, 2018

That depends on the type of tests you are aiming for.

I'm talking about all features which gluegun provides

e.g toolbox isn't exposed in the API and I don't want to mock require statements or mocking in general. It should exist a consistent and simple api to test prompts, filesystem etc this is really important. The project was designed to create big cli applications but that's impossible without a proper test setup/methology.

@kyleect
Copy link

kyleect commented Dec 21, 2018 via email

@StarpTech
Copy link
Author

StarpTech commented Dec 21, 2018

I'm not talking about the stability of gluegun itself but about my commands which are composed of them. How can I guarantee that my super command works when I can't or when it's a hassle for every new developer to write simple tests? It would be awesome to provide in memory adapters for Filesystem, prompts, process... Mocking/Spying is great but it shouldn't be the solution for all. I ask for first class testing support.

@jamonholmgren
Copy link
Member

Hey @StarpTech , apologies for the late response here. I've been focused on some other things.

We do need better testing documentation. I am a big believer in integration tests where possible (especially for CLIs!) and so new Gluegun CLIs now come with an integration test built-in. This is new, as of #409.

Here's an example of this generated integration test:

const { system, filesystem } = require('gluegun')
const { resolve } = require('path')

const src = resolve(__dirname, '..')

const cli = async cmd =>
  system.run('node ' + resolve(src, 'bin', 'movie') + ` ${cmd}`)

test('outputs version', async () => {
  const output = await cli('--version')
  expect(output).toContain('0.0.1')
})

test('outputs help', async () => {
  const output = await cli('--help')
  expect(output).toContain('0.0.1')
})

test('generates file', async () => {
  const output = await cli('generate foo')

  expect(output).toContain('Generated file at models/foo-model.ts')
  const foomodel = filesystem.read('models/foo-model.ts')

  expect(foomodel).toContain(`module.exports = {`)
  expect(foomodel).toContain(`name: 'foo'`)

  // cleanup artifact
  filesystem.remove('models')
})

I'll make it a priority to add more documentation around testing in the future. Thanks for bringing this up!

@jamonholmgren jamonholmgren added docs high priority planned We intend to add this feature or refactor in the future. labels Dec 23, 2018
@StarpTech
Copy link
Author

StarpTech commented Dec 23, 2018

Hi @jamonholmgren

I am a big believer in integration tests where possible (especially for CLIs!) and so new Gluegun CLIs now come with an integration test built-in.

Me too but it's not easy to provide simple and reliable helpers for all the tools (axios, filesystem, process, prompts) and different OS without to provide some builtins. I would like have a combination of both, something like this.

const { systemTest, filesystem, httpTest, testUtils } = require('gluegun')
const { resolve } = require('path')

const src = resolve(__dirname, '..')

// The difference between system and systemTest is that it will prepare the result
// for better testing and it can tracks the progress via 'fork' cross-process communication
const cli = async cmd =>
  systemTest.run('node ' + resolve(src, 'bin', 'movie') + ` ${cmd}`)

test('generates file', async () => {
  // create real file system from JSON
  const cleanUp = await testUtils.createFileSystem({
    './README.md': '1',
    './src/index.js': '2',
    './node_modules/debug/index.js': '3',
  })

  const app = await cli('generate foo')

  await testUtils.delay(2)
  
  // Under the hood we could use supertest
  httpTest.onGet('/users').reply(200, users)

  expect(app.output[0]).toContain('Generated file README.md')

  // I'm in a prompt or process execution or template operation?
  // for better debugging experience
  app.state() // returns { command: 'create-readme', state: 'foo' }

  const readme = await filesystem.read('README.md')

  expect(readme).toContain(`# myapp`)

  await httpTest.ensureCalled()
  
  // cleanup artifact
  await cleanUp()
}

@jamonholmgren
Copy link
Member

Great idea @StarpTech. Perhaps we could expose those utilities at require('gluegun/test') or something, to allow for easy access.

@jamonholmgren
Copy link
Member

FYI, here's an article I wrote that is helpful: https://shift.infinite.red/integration-testing-interactive-clis-93af3cc0d56f

@gleisonkz
Copy link

gleisonkz commented Jun 1, 2022

Do we have any news about this topic, is anyone have an idea on how to work with tests without writing on a real file system?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs high priority planned We intend to add this feature or refactor in the future.
Projects
None yet
Development

No branches or pull requests

5 participants