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

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');
});
主站蜘蛛池模板: 洮南市| 青河县| 曲沃县| 新乐市| 宜黄县| 靖宇县| 安丘市| 孝感市| 浏阳市| 大英县| 冷水江市| 福安市| 芦溪县| 岗巴县| 石屏县| 太康县| 朝阳县| 安泽县| 大同市| 衡阳县| 铁岭市| 建水县| 通河县| 潞西市| 昌邑市| 佛坪县| 辽宁省| 温州市| 凉山| 铜川市| 吉安市| 安岳县| 石狮市| 奉节县| 阿坝| 尚志市| 定远县| 西安市| 和静县| 女性| 沁源县|