-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
watcher: remember failures from previous tests #758
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,7 +64,7 @@ Api.prototype._onTimeout = function (runStatus) { | |
|
||
runStatus.handleExceptions({ | ||
exception: new AvaError(message), | ||
file: null | ||
file: undefined | ||
}); | ||
|
||
runStatus.emit('timeout'); | ||
|
@@ -151,7 +151,7 @@ Api.prototype._run = function (files, _options) { | |
// continue to run. | ||
runStatus.handleExceptions({ | ||
exception: err, | ||
file: file | ||
file: path.relative('.', file) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is more consistent with existing behavior in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, but that should be done as a separate task. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed and understood. |
||
}); | ||
|
||
return { | ||
|
@@ -197,7 +197,7 @@ Api.prototype._run = function (files, _options) { | |
|
||
runStatus.handleExceptions({ | ||
exception: err, | ||
file: file | ||
file: path.relative('.', file) | ||
}); | ||
|
||
resolve([]); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,12 +44,10 @@ function Watcher(logger, api, files, sources) { | |
|
||
this.isTest = makeTestMatcher(files, AvaFiles.defaultExcludePatterns()); | ||
|
||
var isFirstRun = true; | ||
this.clearLogOnNextRun = true; | ||
this.runVector = 0; | ||
this.run = function (specificFiles) { | ||
if (isFirstRun) { | ||
isFirstRun = false; | ||
} else { | ||
if (this.runVector > 0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. Of those two I'd prefer There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm trying to avoid implicit conversions. The vector is increasing so There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
var cleared = this.clearLogOnNextRun && logger.clear(); | ||
if (!cleared) { | ||
logger.reset(); | ||
|
@@ -61,6 +59,8 @@ function Watcher(logger, api, files, sources) { | |
logger.start(); | ||
} | ||
|
||
var currentVector = this.runVector += 1; | ||
|
||
var runOnlyExclusive = false; | ||
|
||
if (specificFiles) { | ||
|
@@ -82,6 +82,7 @@ function Watcher(logger, api, files, sources) { | |
this.busy = api.run(specificFiles || files, { | ||
runOnlyExclusive: runOnlyExclusive | ||
}).then(function (runStatus) { | ||
runStatus.previousFailCount = self.sumPreviousFailures(currentVector); | ||
logger.finish(runStatus); | ||
|
||
var badCounts = runStatus.failCount + runStatus.rejectionCount + runStatus.exceptionCount; | ||
|
@@ -95,6 +96,9 @@ function Watcher(logger, api, files, sources) { | |
this.filesWithExclusiveTests = []; | ||
this.trackExclusivity(api); | ||
|
||
this.filesWithFailures = []; | ||
this.trackFailures(api); | ||
|
||
this.dirtyStates = {}; | ||
this.watchFiles(files, sources); | ||
this.rerunAll(); | ||
|
@@ -121,10 +125,8 @@ Watcher.prototype.watchFiles = function (files, sources) { | |
Watcher.prototype.trackTestDependencies = function (api, sources) { | ||
var self = this; | ||
var isSource = makeSourceMatcher(sources); | ||
var cwd = process.cwd(); | ||
|
||
var relative = function (absPath) { | ||
return nodePath.relative(cwd, absPath); | ||
return nodePath.relative('.', absPath); | ||
}; | ||
|
||
api.on('test-run', function (runStatus) { | ||
|
@@ -177,10 +179,68 @@ Watcher.prototype.updateExclusivity = function (file, hasExclusiveTests) { | |
} | ||
}; | ||
|
||
Watcher.prototype.trackFailures = function (api) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this tracking behavior belongs in watcher. Let's enhance Here is a possible API: var testRun = api.run([...listofFiles]);
// someTime later
var previousRun = testRun;
testRun = api.run([...listOfFiles], previousRun); Alternatively, maybe just create an "AggregateStatus" class: var combinedStatus = new AggregateStatus({
previousRun: RunStatus-instance,
currentRun: RunStatus-instance,
files: list-of-files-that-are-being-rerun, // or not being rerun, whichever makes more sense
deleted: list-of-deleted-tests
}); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The current approach is relatively clean. We could do something like that if we're going to move more of the watcher functionality into the API maybe, or when we have a clearer idea of what programmatic interface we need to present to editors plugins. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It's clean enough, but There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. Would be nice to do that later though :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure - as stated below - none of my comments need to hold this up. |
||
var self = this; | ||
|
||
api.on('test-run', function (runStatus, files) { | ||
files.forEach(function (file) { | ||
self.pruneFailures(nodePath.relative('.', file)); | ||
}); | ||
|
||
var currentVector = self.runVector; | ||
runStatus.on('error', function (err) { | ||
self.countFailure(err.file, currentVector); | ||
}); | ||
runStatus.on('test', function (result) { | ||
if (result.error) { | ||
self.countFailure(result.file, currentVector); | ||
} | ||
}); | ||
}); | ||
}; | ||
|
||
Watcher.prototype.pruneFailures = function (file) { | ||
this.filesWithFailures = this.filesWithFailures.filter(function (state) { | ||
return state.file !== file; | ||
}); | ||
}; | ||
|
||
Watcher.prototype.countFailure = function (file, vector) { | ||
var isUpdate = this.filesWithFailures.some(function (state) { | ||
if (state.file !== file) { | ||
return false; | ||
} | ||
|
||
state.count++; | ||
return true; | ||
}); | ||
|
||
if (!isUpdate) { | ||
this.filesWithFailures.push({ | ||
file: file, | ||
vector: vector, | ||
count: 1 | ||
}); | ||
} | ||
}; | ||
|
||
Watcher.prototype.sumPreviousFailures = function (beforeVector) { | ||
var total = 0; | ||
|
||
this.filesWithFailures.forEach(function (state) { | ||
if (state.vector < beforeVector) { | ||
total += state.count; | ||
} | ||
}); | ||
|
||
return total; | ||
}; | ||
|
||
Watcher.prototype.cleanUnlinkedTests = function (unlinkedTests) { | ||
unlinkedTests.forEach(function (testFile) { | ||
this.updateTestDependencies(testFile, []); | ||
this.updateExclusivity(testFile, false); | ||
this.pruneFailures(testFile); | ||
}, 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.
?
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.
It was inconsistent.