原文摘自:https://dmitripavlutin.com/7-architectural-attributes-of-a-reliable-react-component/#6testableandtestedreact
一個被驗證過針對給定的輸入會渲染出符合指望的輸出的組件,稱爲 測試過的(tested) 組件;bash
一個 可測試的(testable) 組件意味着其易於測試架構
如何確保一個組件如指望的工做呢?你能夠說:「我都本身手動試過的呀。」app
若是你打算對每一個組件的每一個改動都手動驗證的話,或早或晚的,你就會跳過這項苦差事了,而小的瑕疵遲早也會出現。單元測試
這就是對組件的自動化驗證,也就是單元測試(unit test),爲什麼重要的緣由。單元測試保證了每次對組件作出的更改後,組件都能正確工做。學習
單元測試並不僅與早期發現 bug 有關。另外一個重要的方面是用其檢驗組件架構化水平優劣的能力。測試
我以爲這句話格外的重要:ui
一個 沒法測試 或 難以測試 的組件,基本上就等同於 設計得很拙劣 的組件.this
組件之因此難以測試時由於其有太多的 props、依賴、引用的模型和對全局變量的訪問 -- 這都是不良設計的標誌。spa
一個架構設計羸弱的組件,就會變成沒法測試的,進而你就會簡單的跳過單元測試,又致使了其保持未測試狀態,這是一個惡性循環。
總之,許多應用爲什麼是未測試狀態的緣由就是不良的組件設計。即使你想動手測試,也無處下手。
以前的文章中說起過 <Controls>
組件。
下面的代碼測試了高度依賴於父組件結構的 <Controls>
版本:
import assert from 'assert';
import { shallow } from 'enzyme';
class Controls extends Component {
render() {
return (
<div className="controls">
<button onClick={() => this.updateNumber(+1)}>
Increase
</button>
<button onClick={() => this.updateNumber(-1)}>
Decrease
</button>
</div>
);
}
updateNumber(toAdd) {
this.props.parent.setState(prevState => ({
number: prevState.number + toAdd
}));
}
}
class Temp extends Component {
constructor(props) {
super(props);
this.state = { number: 0 };
}
render() {
return null;
}
}
describe('<Controls />', function() {
it('should update parent state', function() {
const parent = shallow(<Temp/>);
const wrapper = shallow(<Controls parent={parent} />);
assert(parent.state('number') === 0);
wrapper.find('button').at(0).simulate('click');
assert(parent.state('number') === 1);
wrapper.find('button').at(1).simulate('click');
assert(parent.state('number') === 0);
});
});
複製代碼
<Controls>
測試起來很是複雜,由於它關聯了父組件的實現細節。
測試場景中須要一個額外的 <Temp>
組件,用來模擬父組件,檢驗 <Controls>
是否正確修改了父組件的狀態。
當 <Controls>
獨立於父組件的細節時,測試就簡單了。讓咱們測試一下合理封裝版本的 <Controls>
組件:
import assert from 'assert';
import { shallow } from 'enzyme';
import { spy } from 'sinon';
function Controls({ onIncrease, onDecrease }) {
return (
<div className="controls">
<button onClick={onIncrease}>Increase</button>
<button onClick={onDecrease}>Decrease</button>
</div>
);
}
describe('<Controls />', function() {
it('should execute callback on buttons click', function() {
const increase = sinon.spy();
const descrease = sinon.spy();
const wrapper = shallow(
<Controls onIncrease={increase} onDecrease={descrease} />
);
wrapper.find('button').at(0).simulate('click');
assert(increase.calledOnce);
wrapper.find('button').at(1).simulate('click');
assert(descrease.calledOnce);
});
});
複製代碼
封裝好則測試易,反之不恰當的封裝讓測試變得困難。
可測試性是一個檢驗組件結構良好程度的實踐標準。
轉載請註明出處
長按二維碼或搜索 fewelife 關注咱們哦