Category: Testing
-
Linkedin 發佈一套 iOS 多線程 UI testing 工具 – bluepill
剛剛在 GitHub trending 上看到,Linkedin 在 8 天前發佈一套名為「bluepill」的 iOS parallel UI testing tool. LinkedIn created Bluepill to run iOS tests in parallel using multiple simulators. Bluepill GitHub: https://github.com/linkedin/bluepill 其特點有 Running tests in parallel by using multiple simulators. Automatically packing tests into groups with similar running time. Running tests in headless mode to reduce memory consumption. Generating a…
-
python pip 加速再加速 – 應用於 CI 建構 virtualenv 上
最近在工作上遇到一個問題,我們的程式碼在 push 上 gitlab 後,CI 會自動的做 unittest 來檢查這次的 changes。同時環境是使用 virtualenv + python3。 用 pip 來管理相依套件不是什麼問題,但放上 CI 後就出現了一個很大的問題,CI 在建構 unittest virtualenv 的環境時,每次會把 workspace 清空,重新建立環境,在這個過程中花費最多的是步驟是在 pip 下載所有需要的套件以及編譯上。以我的狀況為例,整個 pip.require/base 中的套件安裝需要 209 秒的時間,如果在需要編譯套件的 slave 上,那就需要更久的時間。 每次推送後都需要等待過久的時間 (7+ min) 來執行 unittest 實在是忍無可忍,對於開發效率實在影響很大,因此去找了一些加速的方式。 1. 加速套件下載 pip 預設的下載方式是將相依的套件全部重新下載,這可以說是最花時間的一個步驟 (即便你有公司的 pypi server),要避免這個狀況,可以在 pip config file 中設定 cache 的使用。 首先建立這個檔案: ~/.pip/pip.conf 接著在裡面加上這些設定: [global] download-cache=/path/to/your/download-cache…
-
測所翻譯 – Testing on the Toilet: Web Testing Made Easier: Debug IDs
原文網址:https://testing.googleblog.com/2014/08/testing-on-toilet-web-testing-made.html Tuesday, August 12, 2014 by Ruslan Khamitov 在每個元素中增加 id 可以讓針對網頁的測試更易於操作 DOM (e.g. WebDriver tests)。考慮到下面兩個只有內文有差異的 DOM: Save button Edit button <div class=”button”>Save</div> <div class=”button”>Edit</div> 在這個例子中,你會如何使用 WebDriver 來與 “Save” 按鈕互動呢?你有許多的選項。其中一個選擇是使用 CSS selector 來互動: div.button 但是,這個方法並不足以認出一個特定的按鈕,而且沒有其他機制可以讓你在 CSS 中以其中的文字過濾。另一個選樣是使用 XPath,這個方法非常的脆弱且不鼓勵使用: //div[@class=’button’ and text()=’Save’] 你的最佳選擇是增加一個獨特的階層式分類 ID,每個 widget 會有一個 base ID,而這個 base ID 會成為其子元素的前綴。以剛剛的按鈕為例,他們的 ID 將會是: contact-form.save-button contact-form.edit-button 在 Google…
-
測所翻譯 – Testing on the Toilet: Writing Descriptive Test Names
原文網址:https://testing.googleblog.com/2014/10/testing-on-toilet-writing-descriptive.html by Andrew Trenk 先來個問題:你要花多久時間來理解下面這個測試程式要做什麼? @Test public void isUserLockedOut_invalidLogin() { authenticator.authenticate(username, invalidPassword); assertFalse(authenticator.isUserLockedOut(username)); authenticator.authenticate(username, invalidPassword); assertFalse(authenticator.isUserLockedOut(username)); authenticator.authenticate(username, invalidPassword); assertTrue(authenticator.isUserLockedOut(username)); } 你大概閱讀了每一行程式 (說不定不只一次) 然後才理解每一行在做什麼。不過,如果一個測試有好的名子,你需要多少時間來理解下面這個測試想要做什麼呢? isUserLockedOut_lockOutUserAfterThreeInvalidLoginAttempts 透過良好的命名,你應該可以只透過閱讀測試程式的名稱,了解這個測試程式的想要測什麼,你甚至不用閱讀他的程式碼。前面提到的測試程式名稱只說明了他想要測試的情境 (scenario) 是 “invalidLogin”,但沒有真正的說明他期望的測試結果是什麼,所以必須要閱讀所有程式碼才能了解他的意圖。 將情境以及預期結果放在測試名稱還有其他的好處: – 如果想要了解一個類別所有的可能的行為,只要閱讀他的測試類別 (Test class) 中的測試名稱就可, 相比於原本需要花費數分鐘甚至是數小時來閱讀測試程式甚至是該類別本身來理解其行為。這對於 code reviews 也是有幫助的,因為你可以快速的了解是不是測試都已經覆蓋到所有可能的 cases。 – 藉由給予測試更為顯式的名子,可以強迫你把一個測試許多不同行為的 testing 拆分為不同的測試。 不然,你可能會想要把針對不同行為來測試的斷言放在同一個測試程式內,時間一久,這會讓整個測試程式膨脹且變得難以理解與維護。 – 測試的行為不一定每次都能從程式碼中清楚的了解其精確行為。如果測試名稱沒有顯式的告知其精確行為,有時候你會需要猜測這個測試到底在做什麼。 – 你可以簡單的了解到還沒有涵蓋進測試的功能。如果你沒有看到測試名子有那個你想要看或測試的行為,那你就知道,這個測試還沒有被實作。 – 當一個測試失敗的時候,你可以立刻知道是什麼功能失效,而不用去看測試程式碼。 . 有許多的 common patterns 來維護一個…
-
測所翻譯 – Testing on the Toilet: What Makes a Good Test?
原文網址:https://testing.googleblog.com/2014/03/testing-on-toilet-what-makes-good-test.html by Erik Kuefler 對於程式的正確性驗證來說,單元測試 (Unit tests) 是一個非常重要的工具。不過,撰寫好的測試遠比只驗證程式正確性還要重要 ─ 好的單元測試要有某些特徵來讓其易於閱讀與維護。 好測試的其中一個特徵是清晰 (Clarity)。 清晰的意思是指一個測試程式,應該被當作是一個易於人類閱讀的文件,描述其正在測試的 API 功能。 測試本身不應該直接介入實作的細節。一個類別的測試名稱,應該要能夠說明這個類別的用途;而他的測試應該被當作是如何使用這個類別的範例。 另外兩個重要的特徵是完整性 (completeness) 與精簡性 (conciseness) 一個測試在包含所有讓你了解其用途的資訊時為完整,以及沒有包含任何會讓你分心的資訊時為最精簡。 下面這個測試範例在並沒有剛剛提到的兩個重要特徵: @Test public void shouldPerformAddition() { Calculator calculator = new Calculator(new RoundingStrategy(), “unused”, ENABLE_COSIN_FEATURE, 0.01, calculusEngine, false); int result = calculator.doComputation(makeTestComputation()); assertEquals(5, result); // Where did this number come from? } 許多會分散注意力的資訊被放入建構子中,且整個測試中最重要的部份被隱藏在一個 helper method…
-
Model-Based Testing for RESTful API
工作需要,要寫 API 相關的 test cases。目前只有先測 API interface 的部份,寫著寫著發現我根本在造重複的輪子,幾乎在做複製貼上跟填空的工作,程式碼大概長的像下面這樣: class Foo_0000: “”” POST /login/token “”” def __init__(self): self.REST_PATH = “/login/token” self.headers = {“content-type”: “application/json”} self.parse_response = {{ 200: self.parse_response_200, 400: self.parse_response_400, 500: self.parse_response_500 }} def post_api(self, payload): payload = json.dumps(payload) r = requests.post(CONFIG.HOST + self.REST_PATH, data=payload, headers=self.headers) return r def parse_response_200(self, payload, r): if self.expect_status_code !=…