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

Add support for nice error messages with assert #2237

Closed
ianstormtaylor opened this issue Dec 7, 2016 · 6 comments
Closed

Add support for nice error messages with assert #2237

ianstormtaylor opened this issue Dec 7, 2016 · 6 comments

Comments

@ianstormtaylor
Copy link

Do you want to request a feature or report a bug?

Feature.

What is the current behavior?

Right now you only get nice assertions from Jest if you use expect.

What is the expected behavior?

It would be awesome to have nice error messages for assert built-in by default, like Ava does, because assert has a lot less downsides than expect.


I realize this is going to be potentially controversial, since many people use expect as their main assertion library, but please hear me out, because I think there are some pretty objectively good reasons to offer an alternative...

1. expect has long, hard to remember method names.

Things like toHaveBeenCalledWith or toBeGreaterThanOrEqual are easy to misspell and forget since they are so long to begin with. And typing them out gets pretty tedious.

2. expect has inconsistent naming schemes.

To solve the "hard to type" problem, expect adds some aliases. But the naming schemes are inconsistent with each other. For example, there is an alias for toHaveBeenCalled named toBeCalled. But the alias for toHasBeenLastCalledWith is not named toBeLastCalledWith, it's just lastCalledWith, which is unexpected.

3. expect uses incorrect grammar.

On top of it already being hard to remember long method names, many method names are not grammatically correct, making it even harder to remember them. For example, it is toBeLessThanOrEqual instead of toBeLessThanOrEqualTo. And it is toHaveBeenCalledTimes. But all of those built-in method names are awkward to say, and thus hard to remember.

4. expect is very unfriendly to non-English speakers.

If you consider the case of someone who isn't a native English speaker, trying to learn conjuctions and verb tenses correctly in English can be hard. But much of expect's API is tied to knowing specific conjuctions and verbs and tenses. For example it's toHaveLength, which is grammatically correct, but it's not easy to remember that it's not toBeLength, especially when "be" is heavily used elsewhere. Or for example it is toContain to check a child element, and not toHave.

This is made even worse by the previous issue, since some of the method names aren't grammatically correct to begin with, so it's even harder for non-English speakers.

5. expect doesn't build on Javascript's built-in functionality.

expect uses very specific method names to allow for nice error messages, which makes sense when you want to try to provide them at runtime. But with the rise of Babel and other source transformations this is no longer a requirement. And once you ditch that requirement, things like power-assert become available, which let you use the native Javascript syntax to express your tests.

Instead of something like:

expect(4).toBeGreaterThanOrEqualTo(0)
expect(value).not.toBeUndefined()
expect(string).toHaveLength(3)

You get to write:

assert(4 >= 0)
assert(value !== undefined)
assert(string.length == 4)

Which are readable by anyone who knows Javascript, without having to learn an API, without having to know English well, and without having to type long strings.

And they allow for more flexibility, because, "it's just Javascript". I think this is similar to how JSX gives you so much more flexibility over previous templating systems.


All of these issues add up to having to refer to the documentation much more often than should be necessary, and also having to write a lot more verbose assertions that should be necessary.

I open this not to start a fight, but because I think Jest's goal is pretty awesome, and I think including something like power-assert would make it even better.

@cpojer
Copy link
Member

cpojer commented Dec 7, 2016

I don't think this is controversial, there are two pieces to this:

  • Make assert better. I think @DmitriiAbramov mentioned the error thrown from assert has some special stuff in it, so we can use that. The only problem is we are still using Jasmine, so it might be a bit annoying to make it work. Maybe Dmitrii has some suggestions.
  • A completely new, better assertion API. Right now we mimic Jasmine because it is pretty good. I agree with some of your points but in general expect is really, really good. However, I do want diversity in both assertion libraries and test runners. One of the coolest things I believe would be to ship Ava's test runner and assertion library by default in Jest. It would combine the strengths of both to make one super framework: Jest's scalability, snapshots, failure messages and awesome CLI/watch and Ava's far superior APIs. This is a much longer term thing and I'm excited about the potential here.

Finally, I am gonna put the hammer down a bit on "power-assert". I think it is way too crazy as a default. I don't wanna do anything to prevent you from using it though and you should already be able to, no? If no, then that should be fixed separately. We spent a ton of time making failures look really good and helpful this half and while we could bikeshed forever, the status quo is pretty and gives good signal.

None of the things I mention here are actively being worked on so whatever solution you think makes sense, taking it to a PR will make it more likely to get into Jest. Code wins arguments.

@aaronabramov
Copy link
Contributor

aaronabramov commented Dec 13, 2016

built-in assert generates an error that can be caught and prettyfied (mocha does this well)
This is actually something that we need to do at some point, just because some projects rely on native assert and unformatted errors look very confusing.
eslint rule tester is one of those projects. It work great with mocha, but with jest it throws errors with no information about what happened at all. (see eslint/eslint#6532)

here's an example of an assert error.
screen shot 2016-12-12 at 8 21 34 pm

however, when using assertion like this:
screen shot 2016-12-12 at 8 13 28 pm

all you get is expected true to be false which is not really informative. And i don't think there's any way to get any meaningful information from there without static analysis (like power assert does).

I think the best option for now is to make expect as nice as possible and maybe simplify some methods + provide much nicer documentation

@thymikee
Copy link
Collaborator

@cpojer @DmitriiAbramov can we close this issue then?

@aaronabramov
Copy link
Contributor

i guess we're not going to get here anytime soon.
here's another issue for this #1230

we should add a list of first bug tasks for other people who want to start contributing :)

@caub
Copy link

caub commented Dec 9, 2017

Yes, same here, I really can't be bothered to learn or use (I guess it autocompletes though) all those expect(foo).to.have.some... I really can't understand why it's so popular

I made https://github.com/caub/deep-eq beause it's often useful to test deep objects, and I use it like in the first comment, for every assertions. One API to learn

I really wish Jest would support something like this natively!

@github-actions
Copy link

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 13, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants