1. 程式人生 > >【odoo14】第十八章、自動化測試

【odoo14】第十八章、自動化測試

當我們開發大型應用的時候,通過自動化測試可以大幅提高應用的健壯性。每年,odoo都會發布新版本,自動化測試對於應用的迴歸測試非常有幫助。幸運的是,odoo框架有不同自動化測試用例。odoo主要包括三種測試方案: * Python test case: 用於測試Python的業務邏輯測試 * JavaScript Qunit test: 用於測試JavaScript的實現 * Tours: 用於測試Python和JavaScript的互動情況 本章包含: * 新增python測試用例 * 執行python測試用例 * 為客戶端側的測試用例配置(Headless Chrome) * 新增客戶端側的QUnit測試用例 * 新增嚮導的測試用例 * 執行客戶端側的測試用用例 * 除錯測試端側的測試用例 * 為失敗的測試用例生成視訊或螢幕截圖 * 為測試填充隨機資料 # 技術需求 本章,我們將詳細討論測試用例的情況。為了能覆蓋所有的應用場景,我們建立了一個新的模型。模型如下: ``` class LibraryBook(models.Model): _name = 'library.book' name = fields.Char('Title', required=True) date_release = fields.Date('Release Date') author_ids = fields.Many2many('res.partner', string='Authors') state = fields.Selection( [('draft', 'Not Available'), ('available', 'Available'), ('lost', 'Lost')], 'State', default="draft") color = fields.Integer() def make_available(self): self.write({'state': 'available'}) def make_lost(self): self.write({'state': 'lost'}) ``` 對於JavaScript的測試用例,我們將使用第十五章中"建立使用者小部件"一節中的int_color小部件。 你可以在 (github)[ https://github.com/PacktPublishing/Odoo-14-Development-Cookbook-Fourth-Edition/tree/master/Chapter18/00_initial_module] # 新增python測試用例 Python的測試用例用於測試業務邏輯的可用性。第五章,“伺服器側開發-基礎篇”,我們瞭解瞭如何調整現有業務邏輯。由於對現有模型的修改有可能會破壞原有的邏輯,測試就顯得尤為重要。在本節,我們將建立用於驗證改變圖書狀態的業務邏輯。 ## 準備 ## 步驟 1. 新增檔案tests/\_\_init__.py ``` from . import test_book_state ``` 2. 新增tests/test_book_state.py檔案 ```python from odoo.tests.common import TransactionCase class TestBookState(TransactionCase): def setUp(self, *args, **kwargs): super(TestBookState, self).setUp(*args, **kwargs) self.test_book = self.env['library.book'].create({'name': 'Book 1'}) def test_button_available(self): '''Make available button''' self.test_book.make_available() self.assertEqual( self.test_book.state, 'available', 'Book state should be changed to available') def test_button_lost(self): '''Make lost button''' self.test_book.make_lost() self.assertEqual( self.test_book.state, 'lost', 'Book state should be changed to lost') ``` 3. 執行測試用例 ``` ./odoo-bin -c server.conf -i my_library --test-enable ``` 檢視執行日誌,測試用例資訊如下 ``` ... INFO test odoo.addons.my_library.tests.test_ book_state: Starting TestBookState.test_button_available ... ... INFO test odoo.addons.my_library.tests.test_book_state: Starting TestBookState.test_button_lost ... ... INFO test odoo.modules.loading: Module my_library loaded in 0.79s (incl. 0.12s test), 179 queries (+10 test) ``` 如果報錯,"INFO"》》"ERROR"。 ## 原理 在odoo中,測試用例新增在tests/目錄。odoo將自動識別該目錄並執行測試用例。 > 注意 > 我們需要在tests/\_\_init__.py檔案中新增我們的測試用例。 Odoo中使用了python的unittest包。詳細瞭解見 https://docs.python.org/3.5/library/ unittest.html。odoo通過對unittest的簡單封裝,實現了多個非常有幫助的類,可用於簡化測試用例。在我們的例子中,我們使用了TransactionCase。現在TransactionCase可在單獨的食物中執行測試用例。在測試用例執行成功後,將會回滾。意味著,下一個測試用例也將在初始化的環境下執行。 以test_開頭的類方法將被認為是測試用例。在我們的例子中,我們添加了兩個測試用例。可用於檢查圖書的狀態。self.assertEqual方法可用於檢查測試用例是否執行正常。 > 重要資訊 > setUp()方法將在每一個測試用例前執行,因此在本節,我們添加了兩個測試用例,因此setUp()將呼叫兩次。TransactionCase將負責在每次測試用例執行完後進行回滾。 ## 更多 測試單元中還提供瞭如下測試類: * SingleTransactionCase: 所有的測試用例將在一個事務中執行,因此第一個測試用例中對記錄的修改將體現在第二個測試用例中。所有的測試用例執行完成後再進行回滾。 * SavepointCase: 測試用例將執行在特定的場景下(對記錄進行修改後save point,然後測試用例在此基礎上進行測試)。這可確保在進行大型的測試時,可快速的生成測試資料。我們可通過setUpClass()類進行生產測試資料。 # 執行python測試用例 當我們在啟動odoo例項時傳入--test-enabled,測試用例將在模組完成安裝後立刻執行。如果你想在所有的模組完成安裝後再執行,或者僅想執行某一個模組的測試用例,可通過tagged()裝飾器實現。本章,我們將介紹如何使用該裝飾器。 ## 準備 ## 步驟 1. 新增tagged()裝飾器,並在所有模組完成安裝後執行 ```python from odoo.tests.common import TransactionCase, tagged @tagged('-at_install', 'post_install') class TestBookState(TransactionCase): ··· ``` 2. 執行測試用例 ``` ./odoo-bin -c server.conf -i my_library --test-enable ``` 3. 檢查服務日誌,顯示如下: ``` ... INFO book odoo.modules.loading: 9 modules loaded in 1.87s, 177 queries (+0 extra) ... INFO book odoo.modules.loading: Modules loaded. ... INFO book odoo.service.server: Starting post tests ... INFO book odoo.addons.my_library.tests.test_book_ state: Starting TestBookState.test_button_available ... ... INFO book odoo.addons.my_library.tests.test_book_ state: Starting TestBookState.test_button_lost ... ... INFO book odoo.service.server: 2 post-tests in 0.14s, 10 queries ``` 如上顯示在所有模組完成安裝後(post_install)執行測試用例。 ## 原理 預設,測試用例被標記為*standard, at_install及模組的名稱*。因此,如果你並沒有使用tagged裝飾器,將預設是如上標識。 在我們的案例中,我們希望在安裝所有模組之後執行測試用例。為此,我們向TestBookState類添加了一個tagged()裝飾器。預設情況下,測試用例具有at_install標記。由於這個標記,您的測試用例將在模組安裝後立即執行;它不會等待其他模組被安裝。我們不希望這樣,所以為了刪除at_install標記,我們向標記函式添加了-at_install。以-為字首的標籤將刪除該標籤。 通過向tagged()函式新增-at_install,我們在模組安裝後停止了測試用例的執行。由於我們沒有在這裡指定任何其他標記,測試用例將不會執行。 因此,我們添加了一個post_install標記。這個標記指定測試用例需要在所有模組安裝完成後執行。 如您所見,預設情況下,所有的測試用例都是用標準標記標記的。Odoo將執行所有用標準標籤標記的測試用例,以防您不想一直執行特定的測試用例,而只想在被請求時執行測試用例。要做到這一點,你需要通過在tagged()裝飾器中新增-standard來移除standard標籤,你需要新增一個像這樣的自定義標籤: ``` @tagged('-standard', 'my_custom_tag') class TestClass(TransactionCase): ··· ``` 在使用--test-enable時所有非標的測試用例將不會執行。可通過--test-tags=name執行目標測試用例,如下: ``` ./odoo-bin -c server.conf -i my_library --test-tags=my_custom_ tag ``` ## 更多 在測試用例的開發過程中,只為一個模組執行測試用例是很重要的。預設情況下,模組的技術名稱是作為標記新增的,因此可以使用模組的技術名稱和--test-tags選項。例如,如果你想為my_library模組執行測試用例,那麼你可以這樣執行伺服器: ``` ./odoo-bin -c server.conf -i my_library --test-tags=my_library ``` 這裡給出的命令將執行my_library模組中測試用例,但是它仍然會根據at_install和post_install選項來決定順序。 # 為客戶端側的測試用例配置Headless Chrome Odoo使用Headless Chrome來執行JavaScript測試用例和tour測試用例。Headless Chrome是一種不需要完整UI就可以執行Chrome的方法。這樣,我們就可以在與終端使用者相同的環境中執行JavaScript測試用例。在這個食譜中,我們將安裝Headless Chrome和其他包來執行JavaScript測試用例。 ## 步驟 您將需要安裝Chrome來啟用JavaScript測試用例。對於模組的開發,我們主要使用桌面作業系統。因此,如果你的系統上安裝了Chrome瀏覽器,那麼就不需要單獨安裝。您可以使用桌面Chrome執行客戶端測試用例。請確保您的Chrome版本高於Chrome 59。Odoo也支援Chromium瀏覽器。 > 小貼士 > Headless Chrome客戶端測試用例在macOS和Linux上執行良好,但Odoo不支援Windows上的Headless Chrome測試用例。 當您想要在生產伺服器或伺服器作業系統上執行測試用例時,情況會略有變化。伺服器作業系統沒有GUI,所以你需要安裝不同的Chrome。如果你使用的是基於debian的作業系統,你可以使用以下命令安裝Chromium: ``` apt-get install chromium-browser ``` > 重要資訊 > Ubuntu 18.04伺服器版預設沒有啟用universe儲存庫。因此,有可能安裝鉻瀏覽器將顯示安裝候選錯誤。要修復此錯誤,可以使用以下命令啟用universe儲存庫:sudo add-apt-repository universe。 Odoo還支援WebSockets用於JavaScript測試用例。為此,Odoo使用websocket客戶端Python庫。要安裝它,使用以下命令: ``` pip3 install websocket-client ``` ## 原理 Odoo使用無頭瀏覽器進行JavaScript測試用例。這背後的原因是它在後臺執行測試用例,所以它也可以在伺服器作業系統上執行。Headless Chrome更喜歡在後臺執行Chrome瀏覽器,而不需要開啟GUI瀏覽器。Odoo在後臺開啟一個Chrome標籤,並開始執行測試用例。它還使用jQuery的QUnit來進行JavaScript測試用例。在接下來的幾個食譜中,我們將為自定義JavaScript小部件建立一個QUnit測試用例。 對於測試用例,Odoo在一個單獨的程序中打開了Headless Chrome,所以為了找到在這個程序中執行的測試用例的狀態,Odoo伺服器使用WebSockets。websocket-client Python庫用於管理WebSockets,以便從Odoo伺服器與Chrome通訊。 # 新增客戶端側的QUnit測試用例 在Odoo中,建立新的領域或檢視是非常簡單的。只需幾行XML,就可以定義一個新的檢視。然而,在底層,它使用了大量的JavaScript。在客戶端修改/新增新特性是複雜的,可能會破壞一些東西。大多數客戶端問題不會被注意到,因為大多數錯誤只顯示在控制檯中。因此,在Odoo中使用QUnit測試用例來檢查不同JavaScript元件的正確性。 ## 準備 ## 步驟 按照以下步驟向int_color小部件新增JavaScript測試用例: 1. 新增/static/tests/colorpicker_tests.js ``` odoo.define('colorpicker_tests', function(require){ 'use strict'; var FormView = require('web.FormView'); var testUtils = require('web.test_utils'); Qunit.module('Color Picker Tests',{ beforeEach: function(){ this.data = { book: { fields: { name: {string:"Name", type:"char"}, color: {string:"color", type:"integer"}, }, records: [ {id:1, name:'Book 1', color: 1}, {id:2, name:'Book 2', color: 3} ] } }; } }, function(){ // 步驟2中內容 }); }); ``` 2. 新增QUnit測試用例: ``` QUnit.only('int_color field test cases', async function (assert) { assert.expect(2); var form = await testUtils.createView({ View: FormView, model: 'book', data: this.data, arch: '' + '' + '', res_id: 1, }); await testUtils.form.clickEdit(form); assert.strictEqual(form.$('.o_int_colorpicker .o_ color_pill').length, 10, "colorpicker should have 10 pills"); await testUtils.dom.click(form.$('.o_int_colorpicker .o_color_pill:eq(5)')); assert.strictEqual(form.$('.o_int_colorpicker .o_ color_5').hasClass('active'), true, "click on pill should make pill active"); form.destroy(); }); ``` 3. 在/views/template.xml註冊測試文