最近我們正在使用 React Native 來重寫 Growth 應用,GitHub 地址:growth-ng 。作為一個『諮詢師』,我要再一次地切換技術棧,從混合應用開發轉向 React Native。
重寫 Growth 專案,由於業務內容繁多,也因此變成了一個龐大的工程。為了減少開發的時候,不斷也開現一些錯誤,因此花了一段時間來探索:APP 端的持續部署。因此在這一篇文章裡, 我們將介紹基於下面的幾個框架來搭建持續整合:
React Native 與持續整合伺服器 Travis CI 的使用
單元測試 Jest 及 UI 測試框架 React Test Render
自動化功能測試 Appium
使用 fastlane 來實現持續部署
那麼,先讓我們從持續整合伺服器 Travis CI 講起。
持續整合:Travis CI
我在 GitHub 上建立開源專案的時候,都喜歡用 Travis CI 來作為持續整合伺服器。畢竟它是免費的,而且配置簡單的——我們只需要建立一個 。travis。yml 檔案,隨後再按照規則一個個的填入內容。
在新的 Growth 裡,我們配置 Travis CI 來做下面的一些事情:
配置基礎環境
在 Travis CI 上改用了 Node。js 的包管理工具 npm 為 yarn,並使用了快取的機制來加速構建。實踐上證明,快了十幾秒:
cache: yarn
install:
- yarn install
在正常的持續整合作業中,只會進行 eslint 和單元測試。
script:
- npm run lint
- npm test
單元測試目前是由三個主要的框架構成的:
jest。Facebook 推出的單元測試框架,帶有 mock 功能
react-test-render。用來儲存上一次的 UI 的 snapshot
enzyme。由 Airbnb 推出的單元測試工具,主要用來測試一些行為
執行完測試後,會向 Coveralls 提交測試覆蓋率,還會獲得一份 Code Climate 的『程式碼質量分析』分數(4。0 是滿分~~)
並且我們還配置自動部署,當我們使用 git 命令來打 Tag 時。就會觸發 before_deploy 及 deploy 命令。
在 before_deploy 的時候,將會安裝 Android 的打包環境,並執行打包操作、
在 deploy 的時候,則會執行上傳 apk 包到 GitHub Release 頁面。
如下圖所示:
詳細的配置可以見:Growth NG travis CI 配置
在這個過程中,有幾個坑值得說一下:
使用 openJDK 會出錯,只能使用 oraclejdk8
配置 Android 環境的時候,會遇到 LICENSE 沒有輸入 Y 的問題,可以見before_deploy 欄位
單元測試:Jest + Enzyme
對於測試來說,儘管框架上發生了一些變化,但是它仍然離開不了 equal、mock、stub 這些基本的用法。
如下是一個 Jest 測試的示例:
it(‘should open market in browser’, () => {
const spy = jest。spyOn(Helper, ‘openLink’);
SkillDetailView。openPage(‘https://www。phodal。com/’);
expect(spy)。toBeCalledWith(‘https://www。phodal。com/’);
});
唯一比較麻煩的是,當我們要測試原生的元件,需要在 jest。setup。js 中 mock 這些方法,如下是用來 mock 包 react-native-device-info 中的 getVersion 方法:
jest。mock(‘react-native-device-info’, () => ({
getVersion: jest。fn(),
}));
而 React Test Render 的用法就稍微簡單一些,主要用來測試一些元件的渲染結果:
it(‘renders correctly’, () => {
const tree = renderer。create(
);
const treeJson = tree。toJSON();
expect(treeJson)。toMatchSnapshot();
});
而對於 Componet 中帶有 onPress 等的方法,就需要配置 enzyme 來使用:
it(‘test click book’, () => {
const spy = jest。spyOn(SkillDetailView, ‘openPage’);
const wrapper = shallow(
wrapper。find({ title: ‘CSS禪意花園’ })。props()。onPress();
expect(spy)。toHaveBeenCalled();
});
使用 enzyme,模擬使用者的操作,並做一些斷言。
總的來說,React Native 有一些測試還是不容易寫的。並且諸如 WebView 這樣的元件,在測試的時候會報錯~~。
把測試覆蓋率提上去之後,便開始尋找合適的功能測試框架
React Native 功能測試:Appium
最初我考慮的是 Calabash,但是整合的時候,發現資料比較少。於是,便詢問我司高階老司機 《移動App測試的22條軍規》 的作者黃勇及另外一個資深 QA 梁真的意見,分別收到到了下面的一些框架:
跨平臺:Appium
Android:selendroid
iOS:FBSimulatorControl、XUITest
但是我看了看程式碼兩個不同平臺的程式碼:Swift、Java。嗯,我還是用 Appium 寫 Python、JavaScript 去吧~。Appium 的安裝還是挺麻煩的:
brew install libimobiledevice ——HEAD
brew install carthage
npm install -g appium ios-deploy wd
gem install xcpretty # optional
appium
然後再建立一個 Python 的虛擬環境:
virtualenv venv
。 venv/bin/activate
pip install -r requirements。txt
再寫上一個簡單的 Python 測試就可以了:
。。。
class AppiumTest(unittest。TestCase):
def setUp(self):
self。driver = webdriver。Remote(
command_executor=‘http://127。0。0。1:4723/wd/hub’,
desired_capabilities={
‘app’: os。path。abspath(‘。/android/app/build/outputs/apk/app-release。apk’),
‘platformName’: ‘Android’,
‘deviceName’: ‘Nexus 6P API 25’,
})
def tearDown(self):
self。driver。quit()
class TestRouter(AppiumTest):
def test_goto_discover_page(self):
link = self。driver。find_element_by_xpath(‘//*[@text=“探索”]’)
link。click()
time。sleep(3)
self。driver。find_element_by_xpath(‘//*[@text=“線上資源”]’)
總的來說,測試上和 Selenium 還是蠻像的,我想: Appium = App + Selenium。
因為 Travis CI 的 Agent 的配置並不是那麼理想,我便不在上面執行相應的測試了。
部署:Fastlane
最後,讓我再介紹一下 Fastlane,用它來解決 APP 發版的最後一公里問題。
Fastlane是一組工具套件,旨在實現iOS應用釋出流程的自動化,並且提供一個執行良好的持續部署流程,只需要執行一個簡單的命令就可以觸發這個流程。
它提供了一系列的指令碼,來實現對一些工作的自動化,如:
上傳 APK 包到 Google Play,
上傳 iOS 應用到 iTunes Connect
上傳截圖、版本更新說明
等等的內容
只需要執行一下 brew cask install fastlane,再:
到
專案的目錄
執行下 fastlane init,就可以對 Android 應用的自動化釋出進行設定
到
專案的 ios 目錄
執行下 fastlane init,就會生成相應的 iOS 配置
fastlane 會生成相應的 Appfile 和 Fastfile,並且它還可以支援第三方外掛,如我們採用的蒲公英服務:fastlane-plugin-pgyer。
小結
完成了這些步驟後,我們就可以專注的寫程式碼了~~,歡迎來加入我們,編寫新的 Growth 應用。
歡迎
到 phodal/growth-ng
入坑,也可以加我的微訊號 growth-ren,並說明來意