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

江米小棗tonylua發表於2018-06-20

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

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

一個 可測試的(testable) 元件意味著其易於測試

如何確保一個元件如期望的工作呢?你可以說:“我都自己手動試過的呀。”

如果你打算對每個元件的每個改動都手動驗證的話,或早或晚的,你就會跳過這項苦差事了,而小的瑕疵早晚也會出現。

這就是對元件的自動化驗證,也就是單元測試(unit test),為何重要的原因。單元測試保證了每次對元件做出的更改後,元件都能正確工作。

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

我覺得這句話格外的重要:

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

元件之所以難以測試時因為其有太多的 props、依賴、引用的模型和對全域性變數的訪問 -- 這都是不良設計的標誌。

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

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

總之,許多應用為何是未測試狀態的原因就是不良的元件設計。即便你想動手測試,也無處下手。

案例學習:可測試就意味著設計良好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)


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

轉載請註明出處

[譯] 更可靠的 React 元件:從"可測試的"到"測試通過的"
長按二維碼或搜尋 fewelife 關注我們哦

相關文章