-
Notifications
You must be signed in to change notification settings - Fork 9.3k
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
update smokehouse to do deep result comparisons #1450
Conversation
as an example, if you wanted to test the result of a "manifest-background-color": {
"score": true,
"displayValue": "",
"rawValue": true,
"extendedInfo": {
"value": "#bababa",
"formatter": "null"
},
"name": "manifest-background-color",
"category": "Manifest",
"description": "Manifest contains `background_color`"
}, but much of this is boilerplate and better testable at the audit unit test level (we also don't want to update a bunch of test expectations every time we switch So for your expected result you might write 'manifest-background-color': {
score: true,
extendedInfo: {
value: '#bababa'
}
} This tests only the (In this example the value is really testing the manifest parser (which is tested elsewhere), so a better use of this is in the DBW mega test, where we can check things like violation counts, to make sure all corner cases are correctly found and handled) |
2f7df18
to
d5e9f79
Compare
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 are your thoughts on allowing the expectations to be functions and passing an assert
or some similar chai expect
object (with maybe a non-function type defaulting to .score
equality? Just don't want to find ourselves basically writing a new test comparison assertion library for a lighthouse-specific expectations when there are some pretty good ones out there. It's not super clear to me how this extends to arbitrary comparisons we might want to make (existence of something in a list for example). Yay for improved smokehouse testing! :)
*/ | ||
function reportAssertion(assertion) { | ||
if (assertion.equal) { | ||
console.log(` ${log.greenify(log.tick)} ${assertion.category}: ` + | ||
log.greenify(assertion.actual)); | ||
} else { | ||
console.log(` ${log.redify(log.cross)} ${assertion.category}: ` + | ||
log.redify(`found ${assertion.actual}, expected ${assertion.expected}`)); | ||
if (!assertion.diff) { |
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.
can you flip this if/else? had to pause for what this was meaning !equal && !diff === 'diff was just missing'
:)
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.
done
|
||
// We only care that all expected's own properties are on actual (and not the other way around). | ||
for (const key of Object.keys(expected)) { | ||
// Bracket numbers, but property names requiring quotes will still be unquoted. |
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.
why? do we use this for anything other than informing the user?
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, this is just for nice formatting. myArray.1.value
looked weird :)
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.
haha gotcha
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.
lol myArray.1.value
is what polymer uses for it's API.
The main issue I had was I couldn't find anyone doing one-sided deep equality checking, so that if you don't include something on This isn't so bad (if this is what you mean): // results defined up here somewhere
it('correctly does whatever with manifest-background-color', () => {
const manifestBgColorResult = results.audits['manifest-background-color'];
assert.strictEqual(manifestBgColorResult.score, true);
assert(manifestBgColorResult.extendedInfo);
assert.strictEqual(manifestBgColorResult.extendedInfo.value, '#bababa');
}); but 'manifest-background-color': {
score: true,
extendedInfo: {
value: '#bababa'
}
} scans a lot easier to me.
basically if when walking the expected result the expected value is a function, we call the function here with the actual result, and it can do what it likes. That could return a boolean or, if we wanted, throw an assertion error (which would make deciding what to show in expected vs found a lot easier). This could also be extended to support regexp objects (test against actual) and the numeric string conditionals some people like ( |
d5e9f79
to
b5012e7
Compare
Yeah none that I know of either, but
Basically what I was looking for, SGTM! |
I'll give this a look on the way home. |
'manifest-start-url': true, | ||
// 'cache-start-url': true | ||
'is-on-https': { | ||
score: true, |
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.
trailing ",". Fine by me but you don't do this elsewhere.
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.
done
} | ||
}, | ||
'manifest-theme-color': { | ||
score: true |
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.
does this one have a color val we can check?
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, since it was written before extendedInfo
it doesn't include it
'manifest-icons-min-144': { | ||
score: true | ||
}, | ||
'manifest-name': { |
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 assume the name and urls don't have a val we can check?
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 assume the name and urls don't have a val we can check?
nope, none of these older ones do
|
||
// We only care that all expected's own properties are on actual (and not the other way around). | ||
for (const key of Object.keys(expected)) { | ||
// Bracket numbers, but property names requiring quotes will still be unquoted. |
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.
lol myArray.1.value
is what polymer uses for it's API.
return null; | ||
} | ||
|
||
// if they aren't both an object, reject. |
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.
not sure what "reject" means.
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.
Maybe something other than "reject". ...Can't create diff if actual and expected are both not objects.
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.
Good point. Is this more understandable?
b5012e7
to
8b1b4cb
Compare
updated |
⬇️ 🕳 🚬 🔢 💯 |
* update smokehouse to do deep result comparisons * add deeper offline and PWA smoketests expectations
Allows smokehouse expectations to be objects now. Smokehouse will walk the expected value until getting to any primitive leaves, comparing to the actual result at every step, failing if there is any difference. This allows for the expected value to not be complete, so it doesn't have to include noisy details (e.g. audit meta info) better checked by unit tests.
I augmented the PWA and offline smoke test expectations files, but it turns out all those older audits don't include anything that interesting in their extended info (at least compared to newer audits).
manifest-theme-color
doesn't even output what thetheme_color
actually is. We can kick off the DBW deep expectations after this PR.Originally I planned to allow the old expectations format (if it's just a primitive value, assume that it's the
score
property on the actual audit result), but it's really not much work to just explicitly write out the object literal with ascore
property. The literals add considerably to the length of the file, but it means you don't have to keep that special case in mind while writing expectations files. In practice we tend to write these values once and barely touch them again, so it seems fine to be explicit. If others feel strongly about the shorter syntax when you only care about the audit's score, I can add that back in.This doesn't quite finish #964, as this doesn't include comparator support (e.g. if you want to test the actual value with a regex or a floating point comparison (TTI is ≤ 5000 or whatever)), but that's an easy step after these changes.