Airbnbは、ReactテストライブラリであるEnzymeの所有権を、新しい組織であるenzymejs GitHubに譲渡した。Airbnbは引き続きEnzymeを使用し、貢献する予定である。
Airbnbは、コミュニティ主導のenzymejs GitHub組織にEnzymeテストライブラリの開発の役割を移すことを決定した。Airbnbは、決定の背後にある主要な要因が開発者と貢献者のコミュニティからの存在とサポートにあると述べた。
Enzymeの所有権を新しいenzymejs GitHub組織に譲渡することを発表することに興奮している主な理由は、そのコミュニティにあります。この新しいホームは、プロジェクトがコミュニティのニーズを将来にわたってサポートし続けると信じています。ここでの成功が、Airbnbを超えて単一の組織として広がっていきます[…]。
4年経ったReactコンポーネントテストライブラリには、340人を超える貢献者がいる。主要な統計に示されているように、Enzymeは創業以来、開発者の間で人気が高まっている。npmでの毎週200万回のダウンロード(年間8%の増加)、18,000以上のGitHubスター、Enzymeに依存する1,400のパッケージがある。Enzymeはさらに238,000以上のリポジトリと25,000のパッケージで使用されている。
Airbnbは、17,000を超えるテストで内部的にEnzymeを使用していると述べると共に、React Testing Libraryが組織内でますます使用されていることを明らかにした。それにもかかわらず、Airbnbは今後も継続的な使用とEnzymeへの貢献を見込んでいる。
React Testing Library(RTL)は、Reactによって公式に推奨されている。開始以来、npmでのダウンロード数が130万を超えている。RTLは、Reactコンポーネントをテストするための非常に軽量なソリューションであると説明している。その構造化の目標は、実装の詳細に対するテストを回避することで、保守可能なテストを作成できるようにすることである。RTLは、アプリケーションのコンポーネントツリーではなく、アプリケーションの動作に対するテストを奨励することで、その目標を達成しようとしている。RTLの主要な貢献者であるKent C. Dodds氏は、次のように説明している。
テストを作成することを推奨するメソッドとユーティリティのみを公開するよう試みています。それは、どのようにReactコンポーネントを使うかに近いものです。
典型的なRTLテストは、ユーザがブラウザで見るものとまったく同じようにコンポーネントツリーをレンダリングすることで構成される(フルレンダリングあるいはマウント)。次に、開発者は、RTLのAPIを利用して、表示されたコンテンツをクエリし、ユーザイベントをシミュレートできる。そのため、ユーザシナリオは、インターフェイスを介して適切なイベントを再作成し、テスト対象のアプリケーションのユーザが操作するようにインターフェイスの変更を観察することでテストされる。
RTLテストの例の要約は次のとおりである。
(...)
import '@testing-library/jest-dom'
import {render, fireEvent, screen} from '@testing-library/react'
(...)
test('shows the children when the checkbox is checked', () => {
const testMessage = 'Test Message'
render(<HiddenMessage>{testMessage}</HiddenMessage>)
// query* functions will return the element or null if it cannot be found
// get* functions will return the element or throw an error if it cannot be found
expect(screen.queryByText(testMessage)).toBeNull()
// the queries can accept a regex to make your selectors more resilient to content tweaks and changes.
fireEvent.click(screen.getByLabelText(/show/i))
// .toBeInTheDocument() is an assertion that comes from jest-dom
// otherwise you could use .toBeDefined()
expect(screen.getByText(testMessage)).toBeInTheDocument()
})
逆に、Enzymeライブラリを使用する開発者は、浅いレンダリングを使用してコンポーネントツリーに対してテストを実行できる。浅いレンダリングでは、コンポーネントツリーが1レベルの深さでレンダリングされる。EnzymeのShallow Rendering APIは、Reactの抽象レベルの上に提供される、より高いレベルの抽象化である。
浅いレンダリングは、コンポーネントを1つのユニットとしてテストするときに役立つ一方で、子コンポーネントの動作を間接的にテストすることもない。したがって、ラッパーコンポーネントの単体テストを行うと特に便利である。Wasura Wattearachchi氏は、例を使用して浅いレンダリングを示している。<Add>
コンポーネントの浅いレンダリングは次の通りである。
class Add extends Component {
render() {
return (
<div>
<h1>Add Function</h1>
<Form operator='+'/>
</div>
);
}
}
<Form>
が次のように定義されていると仮定する。
<form className='form-group'>
<fieldset className='form-group'>
<label className='form-label'>
First Number:
</label>
<input type="text" id="number1" className='form-input' value={firstNumber} onChange={this.handleFirstNumber}/>
</fieldset>
...
</form>
これにより、<Form>
内の<label>
要素はレンダリングされない。
次はテストファイルである。
import Add from '../src/components/Add';
import Form from '../src/components/Form';
let wrapper;
beforeEach(() => {
wrapper = shallow(<Add />);
});
describe('<Add /> rendering', () => {
it('should render one <h1>', () => {
expect(wrapper.find('h1')).toHaveLength(1);
});
it('should render one <Form>', () => {
expect(wrapper.find(Form)).toHaveLength(1);
});
it('should render 2 <label>s', () => {
expect(wrapper.find('label')).toHaveLength(2);
});
});
最初の2つのテストは合格し、3番目のテストは失敗する。
EnzymeとRTLの両方には、開発者が認識しているように、使用コンテキストがある。Enzymeとその浅いレンダリングを好む人もいれば、RTLとそのフルマウントを常に使用する人もいる。
Enzymeのサポートを求めている開発者は、Enzymeの未解決のIssueやプルリクエストを参考にすることができる。「help wanted」タグが付いており特別にフォーカスされている。