-
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
Customize assertions #1094
Comments
Not at the moment, but your needs can be solved with the existing methods: t.true(object instanceof clazz);
t.is(array.length, length);
t.true(array.every(x => [item, item].includes(x)));
t.true(string.includes(substring)); You can already use any external assertion library. The only caveat is that |
I think a very strong point of AVA (and tape) is precisely that there are few assertions by default - this reduces the amount of 'magic' that occurs, and reduces bugs in testing code that occurs because you aren't 100% sure how a particular assertion works. Given that bugs occur almost as frequently in test code as they do in the code they test, I think it would be a mistake to change this. |
@alathon Being small does not necessarily means being ascetic. t.is(array.length, length); // is better with t.truthy(array) before
t.true(array.every(x => [item, item].includes(x))); // seems cumbersome
t.true(string.includes(substring)); // could be simpler Some basic assertion on strings and arrays seems fair to me — and don't break the 'no magic' of the thing, IMO. |
I guess the problem is that it's a slippery slope. These kind of extra assertions are better in userland as separate modules, functions, or snippets. I personally don't see anything wrong with the code block in the last comment but you could make it look "prettier" by abstracting those functions away. That way you can use your own custom logic as well. The smaller core AVA is, the easier it is to use. |
@sotojuan Good point, totally agree. I think we should make |
I'm in the same boat. I would like to write some custom assertions for convenience and add them to The docs say "you can use custom assertions", but provide no information on how. |
So... what's the easiest way to extend |
@odigity There is no way to do this at the moment. To start we'd need a proposal on a) extending AVA, b) how to register new assertions, and c) how this would integrate with |
So how do you recommend approaching this particular use case? I need to compare two floats with some margin of error. Because there's no support built-in, and no documented way to add custom assertions, I'm currently doing this:
(It's a video processing engine.) It works, but it's ugly compared to, say...
Perhaps with an options arg to control the error margin. almostEquals is a common term used when dealing with floats in JavaScript.
Note: I'm not asking you to implement this, only if there exists a sane way by which one such as myself could do so. |
@odigity I'd do |
@novemberborn But then you don't get the values for I don't see what's wrong with |
For |
Ah, my bad -- was thinking of |
+1 to being able to extend For what it's worth, though, I'd like to see an |
It's really worth making it easy to provide an implementation of custom tests. Right now using |
@lewisdiamond would you want to help us implement this? |
In the meantime, the following hack works for me currently (AVA 2.1.0, 3.15.0): import test from 'ava'
import { Assertions } from 'ava/lib/assert.js'
Object.assign(Assertions.prototype, {
isFoo (value) { this.assert(value === 'foo') },
isBar (value) { this.is(value, 'bar') }
})
test('foobar', t => {
t.isFoo('foo')
t.isBar('bar')
}) The only nits I've spotted are that custom assertions don't support the |
I've used the latter approach to implement https://github.com/gajus/ava-dom As already mentioned by @chocolateboy, the biggest problem is that the error points to the location of Is there a way to workaround this limitation? |
If we could somehow expose a way to report an assertion error I wouldn't be opposed to that. Maybe as a symbol property on #2435 suggests an API to construct custom |
@novemberborn Where do we stand on adding custom assertions to |
Nowhere near starting, let alone shipping.
I don't see how that would be possible? |
Is there anything more to the built-in assertions than being a property of the |
@tommy-mitchell yep! Maybe not top-level but under a namespace, e.g. AVA no longer has power-assert which the start of this thread was concerned with. |
I’ve played around a bit before with adding type definitions to another library that supported custom assertions, using a mapped type with generics can preserve the added assertions and any JSDoc comments on them. |
It might make sense for custom assertion namespaces to begin with an identifier (e.g. For example, say someone publishes some stubbing assertions, and they put them under On a related note, I think user's custom assertions should have a "best practice"/idiomatic namespace, so libraries don't publish their assertions under it. I think t._custom.instanceof(object, class);
t._.includes(string, substring); and then we get cute |
I was thinking about this some more. I reckon if we detect that a built-in assertion is being overwritten, and we log a warning at the end of the CLI output, that'll be enough. Accidental collisions are unlikely and we probably won't add all that many assertions anyhow. Why restrict things. |
That’s fair. I still think having a “custom” namespace be reserved for users is a good idea, though. |
I think, at minimum, we'd need to expose:
Example API: import test as anyTest, {AssertionError} from 'ava';
const test = anyTest.extend(t => ({
includes(string, substring, message) {
// Could also check individually for more precise error messages
if (typeof string !== 'string' || typeof substring !== 'string') {
t.fail(new AssertionError({
assertion: 'includes',
improperUsage: true,
message: '`t.includes()` only accepts strings`',
values: /* concordance stuff */
}));
return false;
}
if (string.includes(substring)) {
t.pass();
return true;
}
t.fail(new AssertionError({
assertion: 'includes',
message,
values: /* concordance stuff */
}));
return false;
},
// ...
}));
test('substring in string', t => {
t.includes('hello world', 'hello', 'Substring not in string!');
}); The custom assertions would be mapped onto the new |
Alternatively we already have the |
Is there a way to add some custom assertions to
t
existing ones?I would like to add those basic ones:
—
t.instanceof(object, clazz)
—
t.length(array, length)
—
t.members(array, item, item)
—
t.includes(string, substring)
I guess
t.context
can be used, but feels cumbersome.And maybe, those assertions can be considered to be added to ava core.
The text was updated successfully, but these errors were encountered: