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

Initial smoke for usage of jest #17

Merged
merged 8 commits into from
Jun 1, 2019
Merged

Initial smoke for usage of jest #17

merged 8 commits into from
Jun 1, 2019

Conversation

SleeplessByte
Copy link
Member

@SleeplessByte SleeplessByte commented May 28, 2019

@tejasbubane I think this will do as initial smoke?

#9

Also adds .babelrc because that's the recommended way to do ts over jest now (NOT ts-jest), should we also look into compiling ts using babel? We lose 4 core features, of which we currently use none.

Not in this PR:

  • actual tests (except for the smoke test)
  • coverage
  • ci

"prepublish": "yarn build",
"test": "ava"
"prepublish": "yarn test",
"test": "yarn build && jest"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't be just "test" : "jest" ?

I tried it and it seems to compile what needed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now, I wanted to have the compilation as a test step. build is NOT the same transformation as jest for now. Jest is relying on babel to strip the types, build is actually compiling via the tsc typescript compiler.

};
`.trim()

const solution = new InlineSolution([solutionContent], exercise)
Copy link
Contributor

@depsir depsir May 29, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this way to create doubles to make a plain string work with the Analyzer.

I feel the need though to test the analyzer to a lower level, for example to exercise checkStructure without involving the solution, the exercise, the runner

I would love something like

    const solutionContent = `
    export const somethingElse = (name = 'you') => {
      return \`One for \${name}, one for me.\`;
    };
    `.trim()

    const program = parseToTree(solutionContent);
    const analyzer = new TwoFerAnalyzer();
    analyzer.program = program;
    expect(analyzer.checkStructure()).toBe("DisapproveWithComment")

Probably this should be discussed in #16 since it involves changing the structure of the analyzer, but I feel that a minimal smoke test for a simple function should be available in this pr

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel the need though to test the analyzer to a lower level, for example to exercise checkStructure without involving the solution, the exercise, the runner

In short: this is possible 👍, using an InlineSolution or something that conforms to the Solution interface:

const analyzerUnderTest = new Analyzer(somethingThatsASolution)
expect(analyzer.method()).toBe(expectedResult)

// Or run it as a whole
const output = analyzerUnderTest.run()
// => AnalyzerOutput({ status: 'some-status', comments: Comment[] })

InlineSolution is really just a ValueObject and passing around strings is Primitive Obsession. I don't think any test benefits from passing around strings 👎 . You can create another test class or method on InlineSolution or global method:

InlineSolution.from(programString)
// => a solution

createSolutionFromString(programString)
// => a solution

The right move forward is probably turning Solution into an interface and create FileSolution and InlineSolution, completely removing the hierarchy, which I only added because I was being lazy 😅

const program = parseToTree(solutionContent);
const analyzer = new TwoFerAnalyzer();
analyzer.program = program;

This is not a good idea:

  • requires exposing program which is an internal state that has nothing to do with the goal of the execution which is coupling implementation and not testing behaviour
  • assumes that we must parse in order to analyse (which is again testing implementation and not behaviour); there are plenty of valid ways to analyse code and an AST might not be applicable for all JavaScript or TypeScript analyzers -- and I don't like to couple the test in that manner.
  • couples the parseToTree with the test; currently this is called only at one single entry point so we can switch out the implementation; but this could be overcome by re-exporting the parsing entry in a local file which is ok.

That said: Running the analyzer without a runner is possible, and we should test it; I will add the tests when testing the analyzer base class -- but not the smoke test. The smoke test is to detect fire, and it should be an reasonably complete e2e test, hitting all the parts. If this fails, something, somewhere, is probably wrong.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@depsir have a look at #18

Copy link
Contributor

@depsir depsir May 30, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like #18. I think you took the good points from my comment above and put them into code.. I would like to clarify some points anyway

InlineSolution is really just a ValueObject and passing around strings is Primitive Obsession. I don't think any test benefits from passing around strings

Not sure about the definition of value object, I would think to some kind of pojo, but the solution has that read method. Not sure about primitive obsession too, in javascript/typescript but I understand its value.
In the end, you did what i meant in #18, where the analyzer takes the string (wrapped in an Input object) as Input directly, without bootstrap, options, solution and so on

requires exposing program which is an internal state that has nothing to do with the goal of the execution which is coupling implementation and not testing behaviour

yes, it was a bad way to express that i wanted the analyzer to take an ast as input. I tried to use what was available in the current api, even though private. I'm not sure that having an ast should be an implementation detail but I can live with that.

just to be clear for any other reviewer, if we have a very simple program to validate (export const color = "blue") we could in theory use a regex without involving a parser. I cannot find other examples where the parser is not needed but It makes [some] sense

About testing the behavior and not the implementation, I think that at some point we will need to unit test some steps of the analysis, e.g. checkForSolutionWithoutStringTemplate of two fer, and this will probably need to setup the analyzer with an already parsed example, i.e. we cannot provide the input and then call execute to parse it, just to test checkForSolutionWithoutStringTemplate.
But as you said, this is a smoke test, where we want to exercise the entire behavior on some of the possible paths. That's why I referred #16 as more appropriate to discuss these structural changes

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about the definition of value object, I would think to some kind of pojo, but the solution has that read method.

Yes, Value Objects are just identified by their value but allow you to attach conversion/casting methods, and use instanceof, implements/extends and so forth, so basically a decorated primitive or set of primitives (or other value objects).

just to be clear for any other reviewer, if we have a very simple program to validate (export const color = "blue") we could in theory use a regex without involving a parser. I cannot find other examples where the parser is not needed but It makes [some] sense

Correct ✔️

@SleeplessByte
Copy link
Member Author

Thank you for the review @depsir ❤️

@SleeplessByte SleeplessByte merged commit 86324e4 into master Jun 1, 2019
@SleeplessByte SleeplessByte deleted the feature/jest branch June 1, 2019 09:05
SleeplessByte added a commit to exercism/typescript-analyzer that referenced this pull request Jun 4, 2019
* Create CODE_OF_CONDUCT (originally @SleeplessByte exercism/javascript-analyzer#5)

* Add dockerfile for automated mentoring support (originally @depsir exercism/javascript-analyzer#12)

* Initial smoke for usage of jest (originally: @SleeplessByte exercism/javascript-analyzer#17)

* Apply design and proper interface and structure (originally: @SleeplessByte exercism/javascript-analyzer#18)

* Fixes issues in the README.md (originally: @zeckdude exercism/javascript-analyzer#19)
SleeplessByte added a commit to exercism/typescript-analyzer that referenced this pull request Jun 4, 2019
* Create CODE_OF_CONDUCT (originally @SleeplessByte exercism/javascript-analyzer#5)

* Add dockerfile for automated mentoring support (originally @depsir exercism/javascript-analyzer#12)

* Initial smoke for usage of jest (originally: @SleeplessByte exercism/javascript-analyzer#17)

* Apply design and proper interface and structure (originally: @SleeplessByte exercism/javascript-analyzer#18)

* Fixes issues in the README.md (originally: @zeckdude exercism/javascript-analyzer#19)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants