摘要:昨天我們使用了庫來編寫我們對組件的第一個測試。是由團隊發布和維護的測試實用程序庫它提供了一個更好的高級的來處理測試中的組件。我們將使用導出的函數來裝載我們的組件。相反我們必須使用提供的方法。
本文轉載自:眾成翻譯
譯者:iOSDevLog
鏈接:http://www.zcfy.cc/article/3806
原文:https://www.fullstackreact.com/30-days-of-react/day-25/
今天,我們將看看一個由Airbnb所維護的開源庫,名為Enzyme,使得測試變得簡單易用。
昨天我們使用了react-addons-test-utils 庫來編寫我們對Timeline 組件的第一個測試。但是, 此庫是相當低級的, 使用起來可能有點麻煩。Enzyme是由 AirBnb 團隊發布和維護的測試實用程序庫, 它提供了一個更好的、高級的 API 來處理測試中的React組件。
我們在測試我們的
我們將使用Enzyme, 使這些測試更容易寫和更可讀。
昨天, 我們寫了我們的第一個測試如下:
import React from "react"; import TestUtils from "react-addons-test-utils"; import Timeline from "../Timeline"; describe("Timeline", () => { it("wraps content in a div with .notificationsFrame class", () => { const wrapper = TestUtils.renderIntoDocument(); TestUtils .findRenderedDOMComponentWithClass(wrapper, "notificationsFrame"); }); })
雖然這是可行的, 但它不是世界上最容易閱讀的測試。當用Enzyme我們重寫它時讓我們看看這個測試的樣子。
我們可以只測試組件的輸出, 而不是用Enzyme來測試完整的組件樹。將不渲染任何組件的子級。這稱為 淺 渲染。
Enzyme使淺渲染超容易。我們將使用Enzyme導出的shallow 函數來裝載我們的組件。
讓我們更新src/components/Timeline/__tests__/Timeline-test.js 文件, 包括從 enzyme導入shallow 函數:
import React from "react"; import { shallow } from "enzyme"; describe("Timeline", () => { it("wraps content in a div with .notificationsFrame class", () => { // our tests }); })
react-addons-test-utils也支持淺渲染。事實上, Enzyme素只是包裝這個函數。雖然昨天我們沒有使用淺渲染, 但如果我們使用它看起來像這樣:
> const renderer = ReactTestUtils.createRenderer(); > renderer.render() > const result = renderer.getRenderOutput(); >
現在, 為了渲染我們的組件, 我們可以使用shallow 方法并將結果存儲在一個變量中。然后, 我們將為在其虛擬 dom 中渲染的不同的React元素 (HTML 或子組件) 查詢 渲染的組件。
整個斷言包括兩行:
import React from "react"; import { shallow, mount } from "enzyme"; import Timeline from "../Timeline"; describe("Timeline", () => { let wrapper; it("wraps content in a div with .notificationsFrame class", () => { wrapper = shallow(); expect(wrapper.find(".notificationsFrame").length).toEqual(1); }); it("has a title of Timeline", () => { wrapper = mount( ) expect(wrapper.find(".title").text()).toBe("Timeline") }) describe("search button", () => { let search; beforeEach(() => wrapper = mount( )) beforeEach(() => search = wrapper.find("input.searchInput")) it("starts out hidden", () => { expect(search.hasClass("active")).toBeFalsy() }) it("becomes visible after being clicked on", () => { const icon = wrapper.find(".searchIcon") icon.simulate("click") expect(search.hasClass("active")).toBeTruthy() }) }) describe("status updates", () => { it("has 4 status updates at minimum", () => { wrapper = shallow( ) expect( wrapper.find("ActivityItem").length ).toBeGreaterThan(3) }) }) })
我們可以使用yarn test命令 (或 npm test 命令) 一樣的方式運行測試:
yarn test
我們的測試通過, 并且更易于閱讀和維護。
讓我們繼續寫斷言, 從我們昨天開始的假設列表中抽取。我們將首先構建我們的測試套件的其余部分, 寫出我們的describe 和it 塊。我們將填寫的規格與斷言后:
import React from "react"; import { shallow } from "enzyme"; import Timeline from "../Timeline"; describe("Timeline", () => { let wrapper; it("wraps content in a div with .notificationsFrame class", () => { wrapper = shallow(); expect(wrapper.find(".notificationsFrame").length).toEqual(1); }); it("has a title of Timeline") describe("search button", () => { it("starts out hidden") it("becomes visible after being clicked on") }) describe("status updates", () => { it("has 4 status updates at minimum") }) })
如果我們遵循測試驅動開發 (簡稱 TDD), 我們將首先編寫這些假設, 然后構建組件以通過這些測試。
讓我們填寫這些測試, 以便它們通過我們現有的Timeline 組件。
我們的標題測試比較簡單。我們將查找標題元素并確認標題為Timeline。
我們希望標題可以在 .title類下使用。因此, 要在規范中使用 .title 類, 我們只需使用Enzyme所暴露的find 函數即可獲取組件。
因為我們的Header組件是 Timeline 組件的子組件, 所以不能使用shallow() 方法。相反, 我們必須使用Enzyme提供的 mount() 方法。
Shallow? Mount?shallow() 渲染函數只渲染我們專門測試的組件, 它不會渲染子元素。相反, 我們將不得不mount() 組件, 因為子組件Header 不可用的 jsdom, 否則。
我們將在本文的末尾看到更多的Enzyme函數。
現在讓我們填寫標題描述:
import React from "react"; import { shallow, mount } from "enzyme"; import Timeline from "../Timeline"; describe("Timeline", () => { let wrapper; it("wraps content in a div with .notificationsFrame class", () => { wrapper = shallow(); expect(wrapper.find(".notificationsFrame").length).toEqual(1); }); it("has a title of Timeline", () => { wrapper = mount( ) // notice the `mount` expect(wrapper.find(".title").text()).toBe("Timeline") }) })
運行我們的測試, 我們將看到這兩個期望通過:
接下來, 讓我們更新我們的搜索按鈕測試。我們在這里有兩個測試, 其中一個要求我們測試一個交互。Enzyme為處理相互作用提供了一個非常干凈的界面。讓我們來看看如何根據搜索圖標編寫測試。
同樣, 由于我們在時間軸中對子元素進行測試, 因此我們必須mount() 元素。因為我們要在一個嵌套的describe()塊中編寫兩個測試, 所以我們可以在幫助器之前編寫一個新的 mount() 來為每個測試重新創建, 這樣它們是純的。
此外, 我們還將使用 input.searchInput 元素進行兩個測試, 因此, 讓我們在前面的幫助器中為該元素編寫.find() 。
describe("Timeline", () => { let wrapper; // ... describe("search button", () => { let search; beforeEach(() => wrapper = mount()) beforeEach(() => search = wrapper.find("input.searchInput")) // ... }) })
若要測試是否隱藏了搜索輸入, 我們只需要知道是否應用了active 類。Enzyme為我們提供了一種使用 hasClass() 方法檢測組件是否有類的方法。讓我們填寫第一個測試, 期望搜索輸入沒有活動類:
describe("Timeline", () => { let wrapper; // ... describe("search button", () => { let search; beforeEach(() => wrapper = mount()) beforeEach(() => search = wrapper.find("input.searchInput")) it("starts out hidden", () => { expect(search.hasClass("active")).toBeFalsy() }) it("becomes visible after being clicked on") // ... }) })
關于第二個測試的棘手部分是, 我們需要點擊圖標元素。在我們看如何做到這一點之前, 讓我們先找到它。我們可以在包裝上的目標通過它的 .searchIcon 類定位到它。
it("becomes visible after being clicked on", () => { const icon = wrapper.find(".searchIcon") })
現在, 我們有了圖標, 我們想模擬一個點擊元素。回想一下, onClick() 方法實際上只是瀏覽器事件的門面。即, 單擊一個元素只是一個通過組件冒泡的事件。而不是控制鼠標或調用元素上的click , 我們將模擬發生在它上的事件。對我們來說, 這將是click 事件。
我們將在icon 上使用simulate() 方法來創建此事件:
it("becomes visible after being clicked on", () => { const icon = wrapper.find(".searchIcon") icon.simulate("click") })
現在我們可以設定一個search 組件具有active 類的期望。
it("becomes visible after being clicked on", () => { const icon = wrapper.find(".searchIcon") icon.simulate("click") expect(search.hasClass("active")).toBeTruthy() })
我們對Timeline 組件的最后期望是至少有四狀態更新。當我們將這些元素放置在Timeline 組件上時, 我們可以 "淺" 渲染組件。此外, 由于每個元素都是自定義組件, 因此我們可以搜索"ActivityItem"類型的特定組件的列表。
describe("status updates", () => { it("has 4 status updates at minimum", () => { wrapper = shallow() // ... }) })
現在, 我們可以測試ActivityItem 組件列表的長度。我們將設定我們的期望, 如果長度至少是4的名單。
describe("status updates", () => { it("has 4 status updates at minimum", () => { wrapper = shallow() expect( wrapper.find("ActivityItem").length ).toBeGreaterThan(3) }) })
我們現在的整個測試套件如下所示:
import React from "react"; import { shallow, mount } from "enzyme"; import Timeline from "../Timeline"; describe("Timeline", () => { let wrapper; it("wraps content in a div with .notificationsFrame class", () => { wrapper = shallow([](#whats-the-deal-with-find)find()處理什么?); expect(wrapper.find(".notificationsFrame").length).toEqual(1); }); it("has a title of Timeline", () => { wrapper = mount( ) expect(wrapper.find(".title").text()).toBe("Timeline") }) describe("search button", () => { let search; beforeEach(() => wrapper = mount( )) beforeEach(() => search = wrapper.find("input.searchInput")) it("starts out hidden", () => { expect(search.hasClass("active")).toBeFalsy() }) it("becomes visible after being clicked on", () => { const icon = wrapper.find(".searchIcon") icon.simulate("click") expect(search.hasClass("active")).toBeTruthy() }) }) describe("status updates", () => { it("has 4 status updates at minimum", () => { wrapper = shallow( ) expect( wrapper.find("ActivityItem").length ).toBeGreaterThan(3) }) }) })
在我們結束今天之前, 我們應該看看一個Enzyme"渲染的界面 (在我們的測試中, wrapper 的對象)。Enzyme文檔 太棒了, 所以我們要保持這個簡短。
基本上, 當我們使用find() 函數時, 我們會將它傳遞給一個選擇器, 它將返回一個ShallowWrapper 實例來包裝找到的節點。find() 函數可以取字符串、函數或對象。
當我們將字符串傳遞給find()函數時, 我們可以傳遞 CSS 選擇器或組件的 _顯示名稱_。例如:
wrapper.find("div.link"); wrapper.find("Link")
我們還可以將它傳遞給組件構造函數, 例如:
import { Link } from "react-router"; // ... wrapper.find(Link)
最后, 我們還可以傳遞對象屬性選擇器對象, 它通過鍵和值來選擇元素。例如:
wrapper.find({to: "/login"});
返回值是一個 ShallowWrapper, 它是一種ShallowWrapper類型 (我們可以渲染包裝和淺包裝)。這些 Wrapper 實例有一組功能, 我們可以使用這些函數來針對不同的子組件, 查看 props 和 state,的方法, 以及渲染的組件的其他屬性, 如html()和text()。更甚的是, 我們可以把這些調用串在一起。
以 組件為例。如果我們想找到基于所有可用鏈接的鏈接類的 HTML, 我們可以編寫這樣的測試:
// ... it("displays a link tag with the Login text", () => { link = wrapper .find("Link") .find({to: "/login"}) expect(link.html()) .toBe("Login") });
哦!今天有很多新的信息, 但是看看我們是如何快速地用Enzyme來編寫后續測試的。閱讀的速度要快得多, 而且更容易辨別實際發生的事情。
明天, 我們將繼續我們的測試旅程和通過集成測試測試我們的應用。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/87161.html
摘要:今天我們將討論創建組件的最終方案,即無狀態函數的純組件。今天我們正在研究一種處理提出的復雜數據的方法,稱為體系結構。第天部署介紹今天,我們將探討部署我們的應用所涉及的不同部分,以便外界可以使用我們的應用。 本文轉載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3758原文:https://www.fullstackreact.com/3...
摘要:我們將討論三種不同的軟件測試范例單元測試功能測試和集成測試。在中單元測試通常不需要瀏覽器可以快速運行不需要寫入斷言本身通常是簡單而簡潔的。集成測試最后我們將研究的最后一種測試是集成測試。 本文轉載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3809原文:https://www.fullstackreact.com/30-days-of...
摘要:包包含由團隊提供的測試實用程序。將在一個名為的目錄中自動查找整個樹中的測試文件是的帶有下劃線。讓我們為時間軸組件創建第一個測試。其中之一是命令。現在我們已經編寫了第一個測試并確認了我們的設置我們將在明天開始測試我們的時間軸組件。 本文轉載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3807原文:https://www.fullstac...
摘要:我們的第一個假設是非常簡單的測試。我們正在測試以確保元素被包裝在類中。在我們編寫的每個測試中我們都需要將應用呈現在工作測試文檔中。作為提醒我們可以使用命令或命令來運行測試。 本文轉載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3804原文:https://www.fullstackreact.com/30-days-of-react/...
摘要:今天我們將討論創建組件的最終方案,即無狀態函數的純組件。為了獲得更多的性能和簡單性,同樣允許我們使用正常的函數創建純粹的,無狀態的組件。在中,功能組件被稱為一個參數的類似于構造函數類,它們是它所調用的,以及組件樹的當前。 本文轉載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3819原文:https://www.fullstackrea...
閱讀 3384·2023-04-26 01:46
閱讀 2906·2023-04-25 20:55
閱讀 5471·2021-09-22 14:57
閱讀 2974·2021-08-27 16:23
閱讀 1712·2019-08-30 14:02
閱讀 2063·2019-08-26 13:44
閱讀 644·2019-08-26 12:08
閱讀 2951·2019-08-26 11:47