A few days ago, I started to look into multiple areas to improve my testing technics. And one of them being using fixtures to improve consistency among my various unit tests and reduce repetitive initialisations of test data in each unit test.
So what is test fixture? According to Wiki, a test fixture is something used to consistently test some item, device, or piece of software.
The advantage of a test fixture is that it allows for tests to be repeatable since one is always starting with the same setup every time. Test fixtures also ease test code design by allowing the developer to separate methods into different functions and reuse each function for other tests. It also preconfigures tests into a known state at start instead of working with whatever was left from a previous test run.
So basically a test fixture helps us to have a fixed pre setup test environment.
Let’s take an example to see how to implement a fixture:
//fixture.tsx
export const items = [
{
key: "item 1",
item: "item 1",
},
{
key: "item 2",
item: "item 2",
},
{
key: "item 3",
item: "item 3",
},
];//Dropdown.tsximport React from "react";
import { MenuItem } from "@blueprintjs/core";
import {
Select,
ISelectProps,
ItemRenderer,
IItemRendererProps,
} from "@blueprintjs/select";
export type dropdownItem = {
key: string;
item: string;
};
export const Dropdown = Select.ofType<dropdownItem>();
export const renderDropdownItem: ItemRenderer<dropdownItem> = (
item,
itemProps: IItemRendererProps
) => {
return <MenuItem key={item.key} active={true} text={item.item} />;
};
export type IDropdownProps<T> = ISelectProps<T>;//Dropdown.spec.tsximport React from "react";
import { mount } from "enzyme";
import { Dropdown, renderDropdownItem } from "./dropdown";
import { items } from './dropdown.fixture'
describe("Select", () => {
it("renders select with items", () => {
const wrapper = mount(
<Dropdown itemRenderer={renderDropdownItem} items={items} onItemSelect={() => { }} />);
expect(wrapper).toMatchSnapshot();
});
it("renders select", () => {
const wrapper = mount(<Dropdown itemRenderer={renderDropdownItem} items={[]} onItemSelect={() => { }} />);
expect(wrapper).toMatchSnapshot();
});
});//Dropdown.stories.tsx
import React from "react";
import { storiesOf } from "@storybook/react";
import { Dropdown, renderDropdownItem } from "./dropdown";
import { items } from "./dropdown.fixture";
const renderDropdown = () => {
return (
<Dropdown
itemRenderer={renderDropdownItem}
items={items}
onItemSelect={() => {}}
/>
);
};
storiesOf("Form/dropdown", module).add("default", () => renderDropdown());
So we first init an items
object with an array of item
object, and in our test file (also .stories
if you are using storybook) we simply require the fixture file, and passing in the items
as items props
to Dropdown
component. Without fixture, we would need to write repetitive test data in both .spec
and .stories
file, and every time when we need to change the test data, we have to change it in both places.
Pretty simple right?