-
Notifications
You must be signed in to change notification settings - Fork 242
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
Bugfix: Stryker init creates a temp folder #361
Bugfix: Stryker init creates a temp folder #361
Conversation
Also:
PS: some time build will be red. |
Todo looks fine indeed. Thanks for picking this up!
That's fine, if your ok with waiting up to a day on answers. Gitter can be faster at times.
We're not using jasmine as a test framework, instead we're using mocha (test framework) and chai (assertion library). It looks like jasmine, but it is not.
True and yes i would like unit tests, but not strictly necessary. We can do that some other time. |
Ok, lets continue with questions in gitter. |
Any ideas ? https://gitter.im/stryker-mutator/stryker?at=59a40add66c1c7c477ecba5c I put back old name and tests became green. I am not sure. Is this correct? |
indeed, the integration tests of the stryker-html-reporter contain a snapshot of the events stryker reporter callbacks, in order to test the integration of stryker-html-reporter without the need to run stryker each time. So it's loosely coupled. I see you changed the expect back to it's original name, i think that's fine. There is no technical reason to keep the events in the stryker-html-reporter in sync with current stryker file names. That would be a waste of time |
For the unit tests, be sure to mock away all the interactions with the file system, as we want our unit tests to be able to run in complete isolation, without any side effects. That is the difference with integration tests, as there we usually test with side effects. Side effects here is creating files stuff. In this case, you should stub |
Okay! So one more item to do is to create new unit tests for refactored class, right? I did all other work? Am I right? Is everything correct? I mean: refactoring of the class to fix the bug. |
Yes looks good! indeed the only thing remaining is add unit tests. |
Ok, cool. I will research how to do this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes looks good! indeed the only thing remaining is add unit tests.
It might be better to not create the temp folder in the constructor. Instead, we should have an Making methods dependent on each other like this is a bad practise, but the only way around that would be to not use a Singleton, instead create an instance of a TempFolder and pass that along. You can do that as well if you choose. The TempFolder is only used during mutation testing. It is the place were we store the sandboxes on disk. A sandbox is a copy of all your files with (possibly) a mutation in one of them. It is where the actual mutation testing occurs. I started a discussion on #366 to see if we can do in-memory testing. If that happens we can delete the So the |
Okay, I updated the code. What do you think? I added initialize method. I will update tests if you think this is ok. https://github.com/stryker-mutator/stryker/pull/361/files#diff-3b57d820a130bce2b8a1d1428567eb28R13 |
Any thoughts? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Already looks good. Had some small remarks on the unit tests.
|
||
beforeEach(() => { | ||
sandbox = sinon.sandbox.create(); | ||
sandbox.stub(StrykerTempFolder, 'writeFile'); | ||
tempFolderMock = mock(TempFolder); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Awesome this works, even with a class with a private constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah true. Damn, i think this is a limitation of typescript. It will work if you you change the mock
:
export function mock<T>(constructorFn: { new(...args: any[]): T; }): Mock<T>;
export function mock<T>(constructorFn: any): Mock<T>;
export function mock<T>(constructorFn: any): Mock<T> {
return sinon.createStubInstance(constructorFn) as Mock<T>;
}
And than use it like this: mock<TempFolder>(TempFolder);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm. Now I am getting this: https://travis-ci.org/stryker-mutator/stryker/jobs/270886353#L1771. Still can not get what is the problem.
|
||
const log = log4js.getLogger('TempFolder'); | ||
|
||
export class TempFolder { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add a private constructor() { }
in order to prevent anyone from creating an instance them selves.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
tempFolderMock = mock(TempFolder); | ||
sandbox.stub(TempFolder, 'instance').returns(tempFolderMock); | ||
tempFolderMock.createRandomFolder.returns(workingFolder); | ||
tempFolderMock.copyFile.resolves({}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! It is indeed better to use stub.resolves
instead of stub.returns(Promise.resolve())
}); | ||
afterEach(() => sandbox.restore()); | ||
|
||
it('TempFolder is presented', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What exactly are you testing here? This test can never fail, right? If one of the methods is missing, we would get a compile error in our production code. The benefit of using typescript, is that we don't need tests like these. You can remove it 👍
In this test, your basically verifying that TypeScript is transpiled correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test will fail if somebody remove/rename this class by accident . This test will force him think about it again. Do you think it is not needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. That's why we use typescript. Having the test won't hurt of course.
import * as mkdirp from 'mkdirp'; | ||
import * as fs from 'mz/fs'; | ||
|
||
describe.only('TempFolder', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the only
here 😺
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, I will. Tests are not ready atm 😿 I will do it of course when I finish to debug my units.
const mockCwd = process.cwd() + '/some/dir'; | ||
sandbox.stub(mkdirp, 'sync'); | ||
sandbox.stub(process, 'cwd').returns(mockCwd); | ||
sandbox.stub(TempFolder.instance(), 'random').returns('rand'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's better to move this stubbing to the top before each. Putting it right here clutters the tests a bit. You can still do the cwdStub.returns(mockCwd)
and randomStub.returns('rand')
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
}); | ||
}); | ||
|
||
xdescribe('constructor logic', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this still be removed? Or changed into the testing of initialize()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it should be changed. Tests are not ready. I will update them since current code is ok (as I am getting from your review). I just wanted to know if TempFolder.ts code is correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed it.
Uhm. I was asking about is current implementation is ok (not tests). Test are not ready at all. Actually, I am ready to put them into a trash. Since everything except units looks good (as I understood from your review) I am going to fix units now. |
❓ @nicojs Do you think TempFolder should generate an exception if some method was called, but |
…-320/temp-directory-creates-on-file-import
* Deletes the Stryker-temp folder | ||
*/ | ||
clean() { | ||
log.debug(`Cleaning stryker temp folder ${this.baseTempFolder}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is word "clean" in that context"? As I understand "clean" means "clean contents of the directory". But purpose of that function is to remove directory completely.
Are you sure this is correct? Perhaps "remove" will be better since it will say what really happens.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, remove
would be better. Yes the purpose is to remove the dir completely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is word "clean" in that context"?
Sorry I wanted to say "is it correct in that context"?
OK! I will fix.
How do you see unit test for
Do you have any examples of units for same things? |
Well... maybe that's smart. It communicates clear intent (but you will need extra unit tests).
You can use the 'test/helpers/streamHelpers.ts'. It has helpers to convert a stream to a string and back. But you can also skip this unit test, as we're not going to use it anymore in the future when we have transpiler support (coming with |
How this unit test will look like if one and first initialize call will influence all tests. Perhaps I can reset state to uninitialised manually after each test. I will not initialize it before each test but only for specific. |
packages/stryker/src/Stryker.ts
Outdated
@@ -81,7 +81,8 @@ export default class Stryker { | |||
this.reporter.onScoreCalculated(score); | |||
ScoreResultCalculator.determineExitCode(score, this.config.thresholds); | |||
await this.wrapUpReporter(); | |||
await StrykerTempFolder.clean(); | |||
TempFolder.instance().initialize(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this one should be moved up right? Right before the initialTestRun
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
That sounds good, but i would do it in a The private constructor seems to work now. I think just moving the call to the initialization |
I added tests. Here is test run output:
|
Also final check is passed: tmp dir is not created on |
Thanks! |
* master: fix(stryker-init): Stryker init won't create temp folder (stryker-mutator#361) Publish fix(stryker task): Guard against clearing the require cache (stryker-mutator#362) (stryker-mutator#369) chore(build): Make build ts 2.5 compatible (stryker-mutator#368)
Impl of #320
TODO: