官术网_书友最值得收藏!

Generating parameterized tests

Some programming languages, such as Java and C#, require special framework support to build parameterized tests. But in JavaScript, we can very easily roll our own parameterization because our test definitions are just function calls. We can use this to our advantage by pulling out each of the existing six tests as functions taking parameter values.

This kind of change requires some diligent refactoring. We'll do the first two tests together, and then you can either repeat for the remaining five tests or jump ahead to the next tag in the Git repository:

  1. Our existing tests use a function named firstNameField. Create a generic version of function that will work for any field, as shown next. It takes a name parameter that must be passed in by the caller to specify which field is being accessed:
const field = name => form('customer').elements[name];
  1. Replace each occurrence of firstNameField() with field('firstName'). You can use find and replace for this.
  2. Run all tests and ensure they are still passing. At this point, you should have 28 passing tests.
  3. Delete the firstNameField function.
  1. Starting with renders as a text box, wrap the entirety of the it call in an arrow function, and then call that function straight after, as shown:
const itRendersAsATextBox = () =>
it('renders as a text box', () => {
render(<CustomerForm />);
expectToBeInputFieldOfTypeText(field('firstName'));
});

itRendersAsATextBox();
  1. Verify that you still have 28 passing tests.
  2. Parameterize this function by promoting the firstName string to a function parameter. You'll then need to pass in the firstName string into the function call itself, as shown here:
const itRendersAsATextBox = (fieldName) =>
it('renders as a text box', () => {
render(<CustomerForm />);
expectToBeInputFieldOfTypeText(field(fieldName));
});

itRendersAsATextBox('firstName');
  1. Again verify that your tests are passing.
  2. Push the itRendersAsATextBox function up one level, and its dependent function, expectToBeInputFieldOfTypeText, into the parent describe scope. That will allow us to use it in subsequent describe blocks.
  3. For the next test, includes the existing value, we can use the same procedure, but this time rather than promoting the string value, Ashley to a parameter, we'll simply replace it with a more generic value. We can do that because the value isn't really important to the test:
We pass in the prop in a generic fashion, using the [fieldName]: syntax to specify the key. This is about as difficult as JSX can get!
const itIncludesTheExistingValue = (fieldName) =>
it('includes the existing value', () => {
render(<CustomerForm { ...{[fieldName]: 'value'} } />);
expect(field(fieldName).value).toEqual('value');
});

itIncludesTheExistingValue('firstName');
  1. Verify your tests are passing and then push itIncludesTheExistingValue up one level, into the parent describe scope.
  2. Repeat steps 5-9 for the remaining four tests. As a hint, the next test for the label will need a second parameter for the label text, and the two tests for submitting existing values and new values will need a second parameter, for the value.
    For reference, here's how the final test might end up looking:
const itSubmitsNewValue = (fieldName, value) =>
it('saves new value when submitted', async () => {
expect.hasAssertions();
render(
<CustomerForm
{ ...{[fieldName]: 'existingValue'} }
onSubmit={props =>
expect(props[fieldName]).toEqual(value)
}
/>);
await ReactTestUtils.Simulate.change(field(fieldName), {
target: { value }
});
await ReactTestUtils.Simulate.submit(form('customer'));
});

itSubmitsNewValue('firstName', 'firstName');

With all that done, your describe block will now quite succinctly describe what the first name field does:

describe('first name field', () => {
itRendersAsATextBox('firstName');
itIncludesTheExistingValue('firstName');
itRendersALabel('firstName', 'First name');
itAssignsAnIdThatMatchesTheLabelId('firstName');
itSubmitsExistingValue('firstName', 'firstName');
itSubmitsNewValue('firstName', 'anotherFirstName');
});
主站蜘蛛池模板: 安陆市| 灵宝市| 会理县| 丁青县| 徐水县| 四会市| 郸城县| 石台县| 娄烦县| 渭南市| 阳西县| 抚远县| 扶沟县| 德钦县| 固原市| 赫章县| 偏关县| 凤阳县| 丹凤县| 于都县| 凤城市| 兖州市| 青田县| 卢龙县| 黄石市| 贵定县| 高碑店市| 河池市| 鹿泉市| 承德县| 通渭县| 台中县| 海林市| 昌吉市| 璧山县| 潮州市| 绩溪县| 广平县| 霍林郭勒市| 昭苏县| 玛纳斯县|