-
Notifications
You must be signed in to change notification settings - Fork 628
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
fix(testing/equals): cater for different class constructor functions #1000
Conversation
By the way, I forgot to mention that I couldn't run the full suite of tests locally, so I was hoping the the pipeline would catch some more failures, which it did. From what I could tell, it seems that the majority are indeed type differences. Some examples: - Uint8Array(4) [
+ [ - Buffer(4) [
+ Uint8Array(4) [ To me they look like legit/expected failures given the type difference. Keen to hear your thoughts. 💭 |
If you're having issues running the test suite, don't hesitate to reach out, either on the Discord server or to someone directly (my email is on my github profile, my inbox is always open) As for the fix itself, I'm not sure I entirely agree that the current behavior is unexpected; JavaScript's type system is based on duck typing, so if an object has property It'd be interesting to see how other existing JavaScript test frameworks handle this before going forward with this fix. |
Thanks for making yourself available! I've managed to go further with the tests, though. For context, I'm running like the workflow describes, in a docker container – if I run into more issues I'll definitely reach out. In relation to other JS test libs, Node's own assert (both Drawing from experience in other dynamically typed languages such as Ruby and Python where duck-typing is prevalent, equality assertions always fail on different types. (opinion notice, take it with a grain of salt 😄) I wouldn't rely on duck typing in tests especially, where we want to ascertain behavior, and being of a certain type conveys that. I wouldn't want to work with "probably" in my tests; I would want to be sure. (please note that I put the word "probably" in quotes to emphasize it, not to mock what you said). |
Thanks for opening the PR @gtramontina! I agree with you that instances of different classes shouldn't be equal to each other - even if they have effectively the same interface (or shape). I think we should go forward with your PR and it's good that it actually caught these discrepancies. Would you mind fixing currently failing tests? |
I'll fix the failing tests when I get some down time and we can take it from there. 👍 Cheers! |
testing/asserts.ts
Outdated
@@ -202,6 +202,9 @@ export function equal(c: unknown, d: unknown): boolean { | |||
if (!(a instanceof WeakRef && b instanceof WeakRef)) return false; | |||
return compare(a.deref(), b.deref()); | |||
} | |||
if (a && b && (a.constructor !== b.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.
Feels like this should go a lot earlier in the check, as it would short circuit much quicker.
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 agree. I tried adding it closer to top, but wasn't being too successful (was getting unexpected failures). So I put it at the end as it was the least disruptive place I could find and make the new test pass. This way I could at least get something out and get feedback. Once I get the rest of the tests fixed, I'll try moving it earlier.
Won't this break a lot of loose comparisons? feels like goes against duck typing too far into strict typing. |
It didn't break that many… Majority of them were related to buffers and arrays (vide 09484d4). Regarding duck typing, I've presented my opinion earlier (#1000 (comment)). Happy to chat more about it… Edit: Ah! You probably meant breaking a lot of comparisons on user-land. Indeed! Good call! If we're moving forward with this, it definitely needs to be tagged as a breaking change! |
Regarding the two remaining failures: The first one seems to be a real issue with - reg: {},
+ reg: /DENOWOWO/, After a preliminary test, it seems that The second failure is on a test that seems to be asserting on an internal state; potentially on a structure that was meant to remain unexported? - TarEntry {
+ { Any thoughts on these? 💭 |
@gtramontina thanks for digging into that, indeed the first failure seems like an actual problem with |
I've literally just pushed some updates… 😅 I'll add some thoughts as inline comments. I've also adjusted the commit message so it is tagged as a breaking change as pointed out by @caspervonb. |
if (value instanceof RegExp) { | ||
target[key] = new RegExp(value); | ||
return; | ||
} |
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'm not quite happy with the fix as it seems deep_assign
is still flawed. I'm not sure about its usecases, given it lives in a _util
directory… Looks like it is supposed to be something private?
Anyway, as fixing this implementation in particular is not the goal of this PR, I guess we could come back to it later.
@@ -397,7 +397,7 @@ Deno.test("untarLinuxGeneratedTar", async function () { | |||
const content = expected.content; | |||
delete expected.content; | |||
|
|||
assertEquals(entry, expected); | |||
assertEquals({ ...entry }, expected); |
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 seems a bit hacky, but given that TarEntry
is a private type, downcasting it to object in order to keep the assertion behaving as before seems to be an ok trade-off (?).
…ions This commit also fixes the tests that required adjustments. BREAKING CHANGE: `assertEquals`, from `testing/assert.ts`, now compares class constructors. Meaning that if two objects are structurally identical but are of different types, the assertion will now fail.
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.
@gtramontina Nice work! LGTM
While writing a polymorphic
Either
, I stumbled upon this weird comparison behavior: I have two classes that are structurally equalclass Left<L> { private value: L }
andclass Right<R> { private value: R }
. When comparing them withassertEquals
fromhttps://deno.land/[email protected]/testing/asserts.ts
, I've received what feels like a false positive.Example
I'm not sure if this is the intended original behavior, but it sure is unexpected. This fix compares whether the object constructors are the same at the very end of the
equals
function.