Skip to content
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

rename t.same() to t.deepEqual() #686

Merged
merged 6 commits into from
Apr 5, 2016

Conversation

kentcdodds
Copy link
Contributor

Do not merge :-)

This is a work in progress PR just to get the conversation started. There are several tests that are failing and I could use some help there I think.

Thoughts?

@mention-bot
Copy link

By analyzing the blame information on this pull request, we identified @kasperlewau, @ariporad and @sotojuan to be potential reviewers

return x.notDeepEqual(val, expected, msg);
};

function deprecationNotice(oldApi, newApi) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect we'll want something a little more robust :-)

@kentcdodds
Copy link
Contributor Author

And shall I just say that because the tests for this project are written in tap rather than AVA, I'm coming to appreciate AVA more and more :-) ❤️

@sindresorhus
Copy link
Member

Thanks for starting the conversation @kentcdodds :)

We'll definitely need a codemod if we're going with this.

@sindresorhus
Copy link
Member

Not to start a bikeshedding, but is there any other word we could use that might be even clearer?

@kentcdodds
Copy link
Contributor Author

Great to explore options for the best API possible while the topic is open for debate. I have no ideas though...

@vadimdemedes
Copy link
Contributor

Here's an idea: what if t.same becomes t.is? Couldn't be clearer and shorter to type. And t.is gets removed in favor of t.true(a === b).

I use t.is only for primitive values and when I need to check that references are equal. t.same also handles primitive values, so the only benefit of t.is is checking reference equality.

What do you think?

@kentcdodds
Copy link
Contributor Author

I'd be fine with that.

@jamestalmage
Copy link
Contributor

I think the best criteria by which to judge is this:

If someone who has never used tap/AVA/chai/etc is reading the test, what gives them the best chance of understanding what the assertion does without looking at the docs. Part of this includes avoiding ambiguity where possible. If a word could mean two different types of assertions, that's a big knock against it (we won't reach perfection here, because English).

Short names should be low on the list of priorities. There is a limit at which something is too long, but a few extra characters is worth any added clarity.

@kentcdodds
Copy link
Contributor Author

Short names should be low on the list of priorities. There is a limit at which something is too long, but a few extra characters is worth any added clarity.

Couldn't agree more.

But I still have no suggestions to a better name than deepEqual :-)

@kasperlewau
Copy link
Contributor

Not to start a bikeshedding, but is there any other word we could use that might be even clearer?

Off of the top of my head, here's a couple of candidates (of varying degrees of suck);

  • t.sameStructure
  • t.distinctEq
  • t.reflect
    • t.reflection
    • t.reflectionOf
  • t.mirror
    • t.mirrorOf
  • t.comparable
    • t.comparableTo
  • t.represent
    • t.representation
    • t.representationOf
  • t.isomorphism
    • t.isomorphicTo

The ones that I do like to some extent would be sameStructure and comparableTo. Possibly distinctEq as well, even though it's somewhat of an oxymoron. Can probably bin the rest swiftly 😄

I reckon sameStructure is the winner here. I find it very hard to misinterpret, and it conveys the intent of the assertion very clearly. I don't quite see it trumping deepEqual though. Just gotta keep crossing off those candidates I suppose..


Here's an idea: what if t.same becomes t.is? Couldn't be clearer and shorter to type. And t.is gets removed in favor of t.true(a === b).

I agree, in parts. It's ridiculously short to type, and I think opting for t.true(a === b) is a good way to go so there's that going for it. But I don't think t.is adequately conveys the intention of comparing two distinct objects of the same structure.

I'm sorry to say I don't have any better suggestions, aside from the list of verbose candidates in my first segment - along with deepEqual.

My dream scenario would be for the deepEquality assertion to die off entirely and we'd have something like t.true(Object.equals(a,b))

In all honesty, I find deepEqual hard to beat - purely based on the fact that it's "widely adopted". It's probably something most of us are already familiar with. If not, it's pretty easy to find out with a quick Google search as it's not widely adopted outside of computer programming from what I can find. same, is, and most of my suggestions above - are and could be.

@jamestalmage
Copy link
Contributor

My concern with t.is is what happens to users who fail to update current t.is assertions. We leave them open to subtle bugs. Also, it doesn't pass the disambiguation test.

@novemberborn
Copy link
Member

Regardless which name we pick we should carefully document which values are considered passing and which aren't. E.g. #630 surfaced that we were requiring constructor equality.

I wonder if the "same" or "equal" part is implicit. You're testing an assertion with an actual and an expected value. t.same() is confusing because obviously you want things to be the same… and then what does t.is() mean?

Given that, how about t.deep()?

@novemberborn
Copy link
Member

Which would lead to t.strict() for t.is(), if we want to go that far.

@kentcdodds
Copy link
Contributor Author

how about t.deep()?

I still prefer deepEqual. To me it's confusing without equal.

@sindresorhus
Copy link
Member

I'm good with deepEqual.

We should really have a codemod for this change before releasing it. Anyone interested in trying to make one (I especially encourage community members to try)? Resources: #644

@jamestalmage
Copy link
Contributor

Anyone interested in trying to make one (I especially encourage community members to try)?

Looping in our AST friends: @twada @jfmengels

@spudly
Copy link
Contributor

spudly commented Apr 1, 2016

Whipped up a quick codemod for this: https://astexplorer.net/#/AbMVMKHZhp

I'm happy to put this in a PR. Where should I put the files? Perhaps in /codemods?

@jfmengels
Copy link
Contributor

@spudly 👍!

I'd create a new project containing the codemods (ava-codemods?). Don't see the value of putting it in the AVA project if it's only going to be run once at the very most.
There is talk about writing other (complex) codemods too in #644.

@jfmengels
Copy link
Contributor

@spudly I improved your code a bit by providing support for notSame --> notDeepEqual (and some necessary refactoring to avoid duplicating) https://astexplorer.net/#/yXo9G9wx9m/1

@spudly
Copy link
Contributor

spudly commented Apr 1, 2016

@sindresorhus, @jamestalmage, @vdemedes, @novemberborn

Opinions about where to put codemods? I was thinking in /codemods but @jfmengels recommended a separate repo. I'll do whatever.

@spudly
Copy link
Contributor

spudly commented Apr 1, 2016

@jfmengels,

Looks good and nice refactor. Guess I forgot about notSame/notDeepEqual because I never use them...

@sindresorhus
Copy link
Member

};

function deprecationNotice(oldApi, newApi) {
console.warn(`DEPRECATION NOTICE: ${oldApi} has been renamed to ${newApi} and will eventually be removed`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should mention the codemods here or at least a link to docs that mention it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely. Would you like a more robust deprecation abstraction, or is this simple function and console.warn sufficient?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could use util.deprecate.

@sindresorhus
Copy link
Member

@kentcdodds We now have a codemod, so this could potentially go into the next release. Would you be able to finish this up and fix the failing tests?

@kentcdodds
Copy link
Contributor Author

Could definitely use some help on this to know why tests are failing. It's confusing with mix of ava and assert :-)

I definitely want to make this happen soon! :D

@sindresorhus sindresorhus changed the title WIP: rename same to deepEqual rename t.same() to t.deepEqual() Apr 4, 2016
@kentcdodds kentcdodds force-pushed the pr/same-to-deepEqual branch from df2d1d0 to ef49c0f Compare April 4, 2016 17:42
@kentcdodds
Copy link
Contributor Author

Updated the deprecation to use util.deprecate (TIL) and added a note about the codemod repo. I'll try to give the failing tests another look, but last time I know I had a bit of trouble with them.

test('.same() should log a deprecation notice', function (t) {
var calledWith;
var originalConsole = console.warn;
console.warn = function () {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Turns out that when using util.deprecate, it actually logs to console.log which is fine, but I can't seem to get this test to work because when I reassign console.log it appears that my reassignment is never called. I'm not sure what's going on here... Any tips appreciated.

Alternatively, we can trust that util.deprecate works and not worry about writing tests for this case... ¯_(ツ)_/¯

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like deprecate calls an undocumented method process.emitWarning.

That ends up causing a warning event to be emitted on process, which seems to be handled by writing to console.error.

So try console.error?

Or just trust that util.deprecate works.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or just trust that util.deprecate works.

If everyone's ok with that, I think that's what I wanna do :-)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Node.js core uses util.deprecate. So I would trust it.

@kentcdodds
Copy link
Contributor Author

Alrighty, this should be ready to go I think. Feedback welcome!

@@ -130,8 +130,6 @@ x.notThrows = function (fn, msg) {
}
};

x.doesNotThrow = util.deprecate(x.notThrows, 't.doesNotThrow is renamed to t.notThrows. The old name still works, but will be removed in AVA 1.0.0. Update your references.');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved this down to the other deprecated APIs

't.same(value, expected, [message])',
't.notSame(value, expected, [message])',
't.deepEqual(value, expected, [message])',
't.notDeepEqual(value, expected, [message])',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bit made things tricky for me in test/test.js which asserts t.is(result.result.assertCount, 1); and there was no real way for me to know that this is what causes assertCount to increment. Still not sure I follow but this fixed it so ¯_(ツ)_/¯

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The power-assert enhancement actually has callbacks (onSuccess, onFailure) that are called with the result of each assertion. That is where we implement assertion tracking.

I think you should probably keep t.same and t.notSame in the patterns until they are officially removed. Otherwise this will break assertionCount for them. Maybe add a test that ensures the assertion count is tracked for those (which we will remove when we drop support).

@kentcdodds
Copy link
Contributor Author

Also, let me know if you want me to squash and clean things up with the commit message or if you're fine using GitHub's fancy new squash and merge feature :-)

@jamestalmage
Copy link
Contributor

We will use GH' squash and merge.

x.notSame = util.deprecate(x.notDeepEqual, getDeprecationNotice('notSame()', 'notDeepEqual()'));

function getDeprecationNotice(oldApi, newApi) {
return `DEPRECATION NOTICE: ${oldApi} has been renamed to ${newApi} and will eventually be removed. See https://github.com/jamestalmage/ava-codemods to help upgrade your codebase automatically.`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't transpile AVA. Can't use string templates on Node 0.10

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, good to know. Will update.

@jamestalmage
Copy link
Contributor

A few notes, mostly related to making sure we are deprecating t.same without breaking it.

Once those are cleared up, LGTM.

@kentcdodds
Copy link
Contributor Author

Updated PR to respond to @jamestalmage's comments. Thanks!

@kentcdodds kentcdodds force-pushed the pr/same-to-deepEqual branch from b9e601c to 4a804f7 Compare April 4, 2016 19:50
*/
same<U>(value: U, expected: U, message?: string): void;
/**
* Assert that value is not deep equal to expected. (DEPRECATED use `notDeepEqual`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move the DEPRECATED warning to the start?

IDE's use these comments for tooltips. So it would be good to have the warning as prominent as possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@jamestalmage
Copy link
Contributor

LGTM.

@novemberborn
Copy link
Member

:shipit:!

@sindresorhus sindresorhus merged commit e9c6cc2 into avajs:master Apr 5, 2016
@sindresorhus
Copy link
Member

Yay for better UX. Thanks for nudging us towards this and doing the work @kentcdodds :)

@kentcdodds
Copy link
Contributor Author

Fantastic! Did we decided on doing truthy/falsy? I'm happy to do that work as well

@sindresorhus
Copy link
Member

Yes. We're going with that. PR super appriciated :)

@kentcdodds kentcdodds deleted the pr/same-to-deepEqual branch April 5, 2016 14:06
sindresorhus added a commit to avajs/atom-ava that referenced this pull request Apr 5, 2016
sindresorhus added a commit to avajs/sublime-ava that referenced this pull request Apr 5, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants