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

More docs #242

Merged
merged 2 commits into from
Oct 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions doc/decisions/0003-zero-dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ Keeping the tool simple, minimal, easy to install and understand.

## Decision

Do not depend on any NPM package unless there's a strong reason to do that. Keep the zero dependence counter as much as possible.
Do not depend on any NPM package unless there's a strong reason to do that. Keep the zero dependence counter as much
as possible.

## Consequences

1. We will be "reimplementing" things, like file handling functions, or `isEmpty` or `isUndefined` type of queries, but that's fine. We want to keep control of that, and we can keep that in a single place, `Utils` (see decision 0002).
1. We will be "reimplementing" things, like file handling functions, or `isEmpty` or `isUndefined` type of queries, but
that's fine. We want to keep control of that, and we can keep that in a single place, `Utils` (see decision 0002).
2. If there's a security problem, we will be 100% sure our code is causing it.
6 changes: 4 additions & 2 deletions doc/decisions/0004-console-ui-and-formatter.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ Reducing complexity in the `ConsoleUI` object and make it more reusable and test

## Decision

`ConsoleUI` now only knows when to output things, but not the contents of messages, which is now responsibility of a `Formatter`. This object can be replaced by other formatters in the future.
`ConsoleUI` now only knows when to output things, but not the contents of messages, which is now responsibility of a
`Formatter`. This object can be replaced by other formatters in the future.

## Consequences

* `Formatter` becomes testable, as well as `ConsoleUI`
* Responsibilities are better split
* There are more control on Node built-in modules, `Formatter` now talks to `console` object, and `ConsoleUI` to `process`
* There are more control on Node built-in modules, `Formatter` now talks to `console` object, and `ConsoleUI` to
`process`
9 changes: 6 additions & 3 deletions doc/decisions/0005-avoiding-test-doubles.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ Accepted

## Context

Tests against the real system instead of test doubles was proven to be useful detecting bugs and exercising better our system.
Tests against the real system instead of test doubles was proven to be useful detecting bugs and exercising better our
system.

## Decision

Avoid introducing test doubles as much as possible. The only allowed exception is to stub/simulate external systems we can't control. Library code should never be stubbed.
Avoid introducing test doubles as much as possible. The only allowed exception is to stub/simulate external systems we
can't control. Library code should never be stubbed.

## Consequences

- Testing with all the real objects that are used in the tool.
- No need to maintain test doubles and their protocol that should match the real objects' protocols.
- Potentially more setup code, objects could be hard to setup because there are no shortcuts. This can be solved by factory methods and/or test helpers.
- Potentially more setup code, objects could be hard to setup because there are no shortcuts. This can be solved by
factory methods and/or test helpers.
7 changes: 5 additions & 2 deletions doc/decisions/0006-avoid-offensive-vocabulary.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ Accepted

## Context

There is an initiative about questioning the technical vocabulary we use, and avoiding some words that are widely used and may offend people. This is a project that adheres to this initiative, therefore...
There is an initiative about questioning the technical vocabulary we use, and avoiding some words that are widely used
and may offend people. This is a project that adheres to this initiative, therefore...

## Decision

Remove all existing technical vocabulary that might be offensive, and prevent those terms to be added in the future. For instance, the use of "master/slave" replaced by "main/replica" (or similar), or "whitelist/blacklist" by "safelist/blocklist" (or similar).
Remove all existing technical vocabulary that might be offensive, and prevent those terms to be added in the future.
For instance, the use of "master/slave" replaced by "main/replica" (or similar), or "whitelist/blacklist" by
"safelist/blocklist" (or similar).

## Consequences

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 10. Use Mutation Testing and define quality thresholds
# 11. Use Mutation Testing and define quality thresholds

Date: 2022-10-24

Expand Down
86 changes: 84 additions & 2 deletions lib/asserter.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,99 @@ const { I18nMessage } = require('./i18n');
const { isStringWithContent } = require('./utils');

class FailureGenerator extends TestResultReporter {
/**
* Makes the current test to explicitly fail, indicating an exceptional scenario.
*
* @example
* fail.with('The code should not reach this point')
*
* @param {String} description A reason to explain why we are explicitly failing.
* @returns {void}
*/
with(description) {
this.report(TestResult.failure(description || I18nMessage.of('explicitly_failed')));
const messageToReport = description || I18nMessage.of('explicitly_failed');
this.report(TestResult.failure(messageToReport));
}
}

class PendingMarker extends TestResultReporter {
/**
* Indicates a test is not ready to be evaluated until the end to produce a final result, so it will be reported as a
* pending result ({@link TestResult#explicitlyMarkedAsPending}). If no reason is provided, an error result
* ({@link TestResult#error}) will be reported instead.
*
* @param {String} reason A required explanation to indicate why this test is not ready.
* @returns {void}
*/
dueTo(reason) {
if (isStringWithContent(reason)) {
this.report(TestResult.explicitlyMarkedAsPending(reason));
} else {
this.report(TestResult.error(this.invalidReasonErrorMessage()));
}
}

invalidReasonErrorMessage() {
return I18nMessage.of('invalid_pending_reason');
}
}

/**
* I am the entry point for generating different types of assertions.
*/
class Asserter extends TestResultReporter {
/**
* Starts an assertion. A call to this method needs to be chained with an expectation, otherwise it does not
* represent a valid assertion.
*
* @example using the {@link isEqualTo} assertion
* assert.that(3 + 4).isEqualTo(7)
*
* @example using the {@link isEmpty} assertion
* assert.that("").isEmpty()
*
* @example using the {@link isNearTo} assertion
* assert.that(0.1 + 0.2).isNearTo(0.3)
*
* @param {*} actual Ths object under test.
* @returns {Assertion} An object that you can use to build an assertion.
*/
that(actual) {
return new Assertion(this._runner, actual);
}

/**
* Expects a given object to be strictly equal to `true`. Other "truthy" values according to Javascript rules
* will be considered not true.
*
* This is a shortcut of the {@link that} syntax followed by a {@link isTrue} assertion.
*
* @example
* assert.isTrue(3 < 4)
*
* @example equivalent version
* assert.that(3 < 4).isTrue()
*
* @param {*} actual - The object you expect to be `true`.
*/
isTrue(actual) {
return this.that(actual).isTrue();
}

/**
* Expects a given object to be strictly equal to `false`. Other "falsey" values according to Javascript rules
* will be considered not true.
*
* This is a shortcut of the {@link that} syntax followed by a {@link isFalse} assertion.
*
* @example
* assert.isFalse(4 < 3)
*
* @example equivalent version
* assert.that(4 < 3).isFalse()
*
* @param {*} actual - The object you expect to be `false`.
*/
isFalse(actual) {
return this.that(actual).isFalse();
}
Expand All @@ -56,6 +121,23 @@ class Asserter extends TestResultReporter {
return this.that(actual).isNotNull();
}

/**
* Expects two given objects to be equal according to a default or custom criteria.
* This is a shortcut of the {@link that} syntax followed by a {@link isEqualTo} assertion.
*
* @example
* assert.areEqual(3 + 4, 7)
*
* @example equivalent version
* assert.that('3' + '4').isEqualTo('34')
*
* @example custom criteria
* assert.areEqual([2, 3], ['x', 'y']], (a, b) => a.length === b.length)
*
* @param {*} actual - The object under test.
* @param {*} expected - The object that you are expecting the `actual` to be.
* @param {Function<any, any>} [criteria] - A two-argument function to be used to compare `actual` and `expected`. Optional.
*/
areEqual(actual, expected, criteria) {
return this.that(actual).isEqualTo(expected, criteria);
}
Expand Down
Loading