[譯] 更可靠的 React 組件:從"可測試的"到"測試經過的"

原文摘自:https://dmitripavlutin.com/7-architectural-attributes-of-a-reliable-react-component/#6testableandtestedreact

一個被驗證過針對給定的輸入會渲染出符合指望的輸出的組件,稱爲 測試過的(tested) 組件;bash

一個 可測試的(testable) 組件意味着其易於測試架構

如何確保一個組件如指望的工做呢?你能夠說:「我都本身手動試過的呀。」app

若是你打算對每一個組件的每一個改動都手動驗證的話,或早或晚的,你就會跳過這項苦差事了,而小的瑕疵遲早也會出現。單元測試

這就是對組件的自動化驗證,也就是單元測試(unit test),爲什麼重要的緣由。單元測試保證了每次對組件作出的更改後,組件都能正確工做。學習

單元測試並不僅與早期發現 bug 有關。另外一個重要的方面是用其檢驗組件架構化水平優劣的能力。測試

我以爲這句話格外的重要:ui

一個 沒法測試難以測試 的組件,基本上就等同於 設計得很拙劣 的組件.this

組件之因此難以測試時由於其有太多的 props、依賴、引用的模型和對全局變量的訪問 -- 這都是不良設計的標誌。spa

一個架構設計羸弱的組件,就會變成沒法測試的,進而你就會簡單的跳過單元測試,又致使了其保持未測試狀態,這是一個惡性循環。

總之,許多應用爲什麼是未測試狀態的緣由就是不良的組件設計。即使你想動手測試,也無處下手。

案例學習:可測試就意味着設計良好i

以前的文章中說起過 <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);
  });
});
複製代碼

封裝好則測試易,反之不恰當的封裝讓測試變得困難。

可測試性是一個檢驗組件結構良好程度的實踐標準。


(end)


----------------------------------------

轉載請註明出處

長按二維碼或搜索 fewelife 關注咱們哦

相關文章
相關標籤/搜索