Reputation: 924
There are few solutions given by Jest in that direction. I have tried out most of the solutions like --findRelatedTests
, --onlyChanged
, --changedSince
. But there are few shortcomings in every solutions. I thought --changedSince
is the best match for me.
jest --changedSince=origin/master --coverage
It mostly covers the basic scenarios like running test files corresponding to the changed source files. But it does not handle few scenarios like if a source-file(say a.js
) is deleted and same(a.js
) is being used(imported) in another file(say b.js
), it does not run tests for any of the files(a.js
or b.js
). It does not seem to run tests for parent files where it was imported.
Is there a clean solution which can handle all the scenarios like file rename/deletion, dynamic imports, running tests for the parent modules where it was imported or any other impact that may happen when you change a source file?
Upvotes: 14
Views: 16241
Reputation: 2169
Quick answer: No.
Long answer: Yes, but it's not that clean or straight forward.
I have achieved this through three steps.
STEP 1:
You can achieve this by a bit of scripting. First you'll want to get a list of all the changed files through Git.
This can be achieved through a function like the below:
const util = require("util")
const exec = util.promisify(require("child_process").exec)
const detectChangedFiles = async () => {
try {
const { stdout, stderr } = await exec("git diff origin/master --name-only")
if (stderr) {
throw new Error(stderr)
}
return stdout.replace(/\n/g, " ").replace(/client\//g, " ")
} catch (error) {
console.log(error)
}
}
STEP 2:
Secondly, you'd wanna get a list of related tests for those files like the below:
const findRelatedTests = async () => {
const changedFiles = await detectChangedFiles()
try {
const { stdout, stderr } = await exec(`jest --listTests --findRelatedTests ${changedFiles}`)
if (stderr) {
throw new Error(stderr)
}
if (!stdout) {
console.log('No tests found for the changed files :)')
} else {
return stdout.replace(/\n/g, " ")
}
} catch (error) {
console.log(error)
}
}
STEP 3:
And finally you'd wanna feed all of those tests to jest to run;
const runRelatedTests = async () => {
const relatedTests = await findRelatedTests()
if (relatedTests) {
try {
const { stdout, stderr } = await exec(`jest --ci --coverage ${relatedTests}`)
if (stderr) {
throw new Error(stderr)
}
} catch (error) {
console.log(error)
}
}
}
One of the limitations of this implementation is that I"m always diffing against the master and that's not a good assumption. In special cases, one may chose to merge against another branch.
This can be handled in a few ways;
Upvotes: 14