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 expectAssertions option to test #103

Closed

Conversation

bompus
Copy link
Contributor

@bompus bompus commented Sep 19, 2021

fixes #102

@bompus
Copy link
Contributor Author

bompus commented Sep 19, 2021

I wasn't sure what to actually name the option, and I'd actually prefer to be able to call t.expectAssertions(2) instead, but that seemed hackish and more complex to implement.

@lorenzofox3
Copy link
Owner

lorenzofox3 commented Sep 23, 2021

I wasn't sure what to actually name the option, and I'd actually prefer to be able to call t.expectAssertions(2) instead, but that seemed hackish and more complex to implement.

if you pass it to the assertion object then t.plan() is the convention I think. If you consider it is a "meta" option of the test and pass it as an option like you did, I would rather call it something like exepectedAssertionCount so the idea of "count" can be read.

Semantically it is a bit in between: yes it is a kind of meta option of the test and yes it can be seen as an assertion on the test.
Although you can't model the latter with a regular pure function as you do for the other assertions.

Copy link
Owner

@lorenzofox3 lorenzofox3 left a comment

Choose a reason for hiding this comment

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

Thanks for the great effort.

I made some suggestions.

All together, I am not sure it is a worthwhile feature but we can keep on with the discussion in the issue thread

@@ -6,7 +6,7 @@ import {
testEndMessage,
} from 'zora-reporters';

const defaultOptions = Object.freeze({ skip: false });
const defaultOptions = Object.freeze({ skip: false, expectAssertions: undefined });
Copy link
Owner

Choose a reason for hiding this comment

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

so expectedAssertionCount would be more appropriate.

I would not set it in the default options, I would simply omit it

Comment on lines +79 to +81
if (expectAssertions !== undefined && assertions.length !== expectAssertions) {
yield assertionMessage(Assert.equal(assertions.length, expectAssertions, 'expectAssertions'));
}
Copy link
Owner

Choose a reason for hiding this comment

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

I think that is not a good idea to use the regular equal operator. Creating a specific operator would be better.

Copy link
Owner

Choose a reason for hiding this comment

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

and instead of adding a message in the stream. you can simply add an assertion result at the end of the routine so it will be considered as a regular assertion:

const createAssertionCountResult = ({ expected, actual }) => ({
  pass: expected === actual,
  operator: 'plan',
  expected,
  actual,
  description: 'assertion count should match',
});

export const test = (description, spec, opts = defaultOptions) => {
  const { skip = false, expectAssertions = undefined } = opts;
  /* ... */

  const testRoutine = (async function () {
    try {
      const start = Date.now();
      const result = await specFn();
      executionTime = Date.now() - start;
      // add an extra assertion if needed
      if (expectAssertions) {
        onResult(
          createAssertionCountResult({
            expected: expectAssertions,
            actual: assertions.length,
          })
        );
      }
      return result;
    } catch (e) {
      error = e;
    } finally {
      done = true;
    }
  })();

  return Object.assign(testRoutine, {
    [Symbol.asyncIterator]: async function* () {

     // no need to yield a specific message here 

    /* ... */
    },
  });
};

and if you wish to have add the method on the assertion API instead, you could do something like:

export const test = (description, spec, opts = defaultOptions) => {
  const { skip = false } = opts;
  const assertions = [];
  let executionTime;
  let done = false;
  let error;
  let plan;

  /* ... */

  const specFn = skip
    ? noop
    : function zora_spec_fn() {
        return spec(
          Object.assign(assertFactory({ onResult }), {
          // extend the API here
            plan(value) {
              plan = value;
            },
          })
        );
      };

  const testRoutine = (async function () {
    try {
      const start = Date.now();
      const result = await specFn();
      executionTime = Date.now() - start;
      // add an extra assertion if needed
      if (plan) {
        onResult(
          createAssertionCountResult({
            expected: plan,
            actual: assertions.length,
          })
        );
      }
      return result;
    } catch (e) {
      error = e;
    } finally {
      done = true;
    }
  })();

  return Object.assign(testRoutine, {
    [Symbol.asyncIterator]: async function* () {
     /* ... same here */
    },
  });
};

@bompus
Copy link
Contributor Author

bompus commented Sep 23, 2021

Upon discussion in #102 , I no longer believe this is necessary. If it comes up again, this will be a good starting poing for implementing the logic though.

@bompus bompus closed this Sep 23, 2021
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.

Add ability to check the exact number of assertion calls per-test
2 participants