【odoo14】【好书学习】第十八章、自动化测试

老韩头的开发日常【好书学习】系列

当我们开发大型应用的时候,通过自动化测试可以大幅提高应用的健壮性。每年,odoo都会发布新版本,自动化测试对于应用的回归测试非常有帮助。在odoo中主要包括三种测试方案:

  • Python test case: 用于测试Python的业务逻辑
  • JavaScript QUnit test: 用于测试JavaScript代码
  • Tours: 用于测试Python和JavaScript的交互情况

本章包含:

  • 添加python测试用例
  • 运行python测试用例
  • 为客户端侧的测试用例配置(Headless Chrome)
  • 添加客户端侧的QUnit测试用例
  • 添加向导的测试用例
  • 通过UI触发客户端侧的测试用例
  • 调试客户端的测试用例
  • 为失败的测试用例生成视频或屏幕截图
  • 为测试填充随机数据

技术需求

本章,我们将详细讨论测试用例的情况。为了能覆盖所有的应用场景,我们创建了一个新的模块。代码如下:

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'})

我们创建的LibraryBook模型,将在python的测试用例中使用,用于验证业务逻辑。对于JavaScript的测试用例,我们将使用第十五章中"创建用户小部件"一节中的int_color小部件。

添加python测试用例

Python的测试用例用于测试业务逻辑的正确性。在第五章,“服务器侧开发-基础篇”,我们了解了如何调整现有模块的业务逻辑。由于对现有模型的修改有可能会破坏原有的逻辑,测试就显得尤为重要。在本节,我们将创建用于验证改变图书状态业务逻辑的测试用例。

准备

步骤

  1. 添加文件tests/__init__.py
from . import test_book_state
  1. 添加tests/test_book_state.py文件
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')
  1. 运行测试用例
./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中使用unittest包作为测试用例。详细了解见 https://docs.python.org/3.5/library/ unittest.html。odoo通过对unittest的简单封装,实现了多个非常有帮助的类,可简化测试用例。在我们的例子中,我们使用了TransactionCase类,该类封装下的每个测试用例函数都将在独立的事务中执行。在测试用例执行成功后,将会回滚。因此下一个测试用例也将在初始化的环境下执行。
以test_开头的类方法将被认为是测试用例。在我们的例子中,我们添加了两个测试用例。可用于检查图书的状态。self.assertEqual方法可用于检查测试用例是否运行正常。

重要信息
setUp()方法将在每一个测试用例前执行,因此我们添加了两个测试用例,因此setUp()将调用两次。TransactionCase将负责在每次测试用例执行完后进行回滚。

更多

测试单元中还提供了如下测试类:

  • SingleTransactionCase: 所有的测试用例将在一个事务中执行,因此第一个测试用例中对记录的修改将体现在第二个测试用例中。所有的测试用例执行完成后再进行回滚。
  • SavepointCase: 测试用例将运行在特定的场景下(对记录进行修改后save point,然后测试用例在此基础上进行测试)。这可确保在进行大型的测试时,可快速的生成测试数据。我们可通过setUpClass()类进行生产测试数据。

运行python测试用例

当我们在启动odoo实例时传入--test-enabled,测试用例将在模块完成安装后立刻执行。如果你想在所有的模块完成安装后再执行,或者仅想执行某一个模块的测试用例,可通过tagged()装饰器实现。本章,我们将介绍如何使用该装饰器。

准备

使用上一节的模块

步骤

  1. 添加tagged()装饰器,并在所有模块完成安装后执行
from odoo.tests.common import TransactionCase, tagged

@tagged('-at_install', 'post_install')
class TestBookState(TransactionCase):
···
  1. 运行测试用例
./odoo-bin -c server.conf -i my_library --test-enable
  1. 检查服务日志,显示如下:
... 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。注意,在at_install前面有一个-哦。
由于我们通过-at_install移除了模块安装完成后执行测试用例。由于在tagged装饰器中没有指定其他的参数,所以整个测试用例也不会被触发。
因此,我们添加post_install标记。这个标记指定在所有模块安装完成后执行测试用例。
通过上面的知识,我们知道了在odoo中的测试用例默认是以standard标识执行的。因此,默认情况下,Odoo将运行所有standard标签标记的测试用例。而我们只希望运行指定的测试用例。因此,我们需要在tagged()装饰器中添加-standard来移除standard标识。如下:

@tagged('-standard', 'my_custom_tag')
class TestClass(TransactionCase):
···

因此在添加了--test-enable参数的情况下运行odoo实例,将不会触发非standard的测试用力。为了执行前面的测试用例,我们需要使用--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中内容
    });
});
  1. 添加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: '<form string="Books">' +
            '<group>' +
            '<field name="name"/>' +
            '<field name="color" widget="int_color"/>' +
            '</group>' +
            '</form>',
        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();
});
  1. 在/views/template.xml注册测试文件
<template id="qunit_suite" name="colorpicker test" inherit_id="web.qunit_suite">
    <xpath expr="." position="inside">
        <script type="text/javascript" src="/my_library/static/tests/ colorpicker_tests.js" />
    </xpath>
</template>

运行测试用例

./odoo-bin -c server.conf -i my_library,web --test-enable

检查日志

... INFO test odoo.addons.web.tests.test_js.WebSuite: console log: "Color Picker Tests" passed 2 tests.

原理

在odoo中,JavaScript测试用例添加在/static/tests目录中。步骤1,我们新增了colorpicker_tests.js文件。我们引入了formView及test_utils。因为我们创建的ini_color小部件是作用于form视图的,因此我们还需要引入web.FormView。
web.test_utils为我们提供了构建js测试用例的实体。如果你不了解js的引入机制,可参考第十四章"扩展CSS及JavaScript"。
odoo的客户端测试用例是通过QUit框架实现了,它是用于JS单元测试的JQuery框架。参考https://qunitjs.com/。beforeEach函数会运行测试用例前执行,可用于初始化测试数据。函数由QUit框架提供。
我们在beforeEach函数中初始化了一些数据。客户端测试用例是运行在一个独立(mock)的环境中,它并不与数据库进行交互。因此,我们需要创建一些测试数据。在内部,odoo创建了虚拟环境模拟RPC,this.data模式数据库。this.data中的keys相当于数据库中表,values相当于表中的字段及行。在我们的例子中,我们添加了book的表,book表有两个字段name(char)及color(integer)。在这,我们可以使用所有的字段类型,比如,{string:"M2oField", type:"many2one", relation:"partner"}。我们在records中添加了两条记录。
下一步,我们借助Quit.test函数创建了测试用例。函数的第一个参数是string类型,用于描述测试用例的用途。第二个参数是具体测试用例代码逻辑的函数。函数由QUnit框架调用,assert实例作为参数传递到函数体内。在我们的例子中,我们在assert.expect函数中传入了测试用例的个数。我们一共有两个测试用例,因此我们传入2。
我们计划测试编辑模式下的int_color小部件。所以我们通过testUtils.createView创建了编辑模式下的form视图。createView接收不同参数:

  • View: 我们创建的视图。
  • model: 视图作用于的模型的名称。
  • data: 模拟数据。
  • arch: 视图的定义内容。
  • res_id: 展示的记录的ID。该选项作用于form视图。在我们的案例中,form视图展示book 1的数据,因为res_id为1。

在使用int_color小部件创建表单视图之后,我们添加了两个测试用例。第一个测试用例用于检查UI上彩色药片的数量,第二个测试用例用于检查药片在单击后是否被正确激活。我们从断言的QUnit框架的效用中得到了严格的函数。如果前两个参数匹配,则strictEqual函数通过测试用例。如果它们不匹配,则测试用例将失败。

更多

还有一些assert函数可以用于QUnit测试用例,比如assert.deepEqual,assert.ok,assert.notOk。要了解有关QUnit的更多信息,请参阅https://qunitjs.com/上的文档。

添加向导的测试用例

现在您已经看到了Python和JavaScript测试用例。它们都在一个孤立的环境中工作,它们彼此之间不相互作用。为了测试JavaScript和Python代码之间的集成,使用了向导测试用例。

准备

对于本节,我们将继续使用上一节中的my_library模块。我们将添加一个巡回测试用例来检查图书模型的流程。另外,确保您已经安装了web_tour模块,或者已经将web_tour模块依赖项添加到清单中。

步骤

按照以下步骤添加图书的向导测试用例:

  1. 添加一个/static/src/js/my_library_tour.js文件:
odoo.define('my_library.tour', function (require) {
    "use strict";
    var core = require('web.core');
    var tour = require('web_tour.tour');
    var _t = core._t;
    tour.register('library_tour', {
        url: "/web",
        test: true,
        rainbowManMessage: _t("Congrats, you have listed a book."),
        sequence: 5,
    }, [tour.stepUtils.showAppsMenuItem(), // Place step 3 here
    ]);
});
  1. 添加测试步骤
{
    trigger: '.o_app[data-menu-xmlid="my_library.library_ base_menu"]',
    content: _t('Manage books and authors in <b>Library app</b>.'),
    position: 'right'
}, {
    trigger: '.o_list_button_add',
    content: _t("Let's create new book."),
    position: 'bottom',
}, {
    trigger: 'input[name="name"]',
    extra_trigger: '.o_form_editable',
    content: _t('Set the book title'),
    position: 'right',
    run: function (actions) {
        actions.text('Test Book');
    },
}, {
    trigger: '.o_form_button_save',
    content: _t('Save this book record'),
    position: 'bottom',
}
  1. 添加到test资源
<template id="assets_tests" name="Library Assets Tests" inherit_id="web.assets_tests">
    <xpath expr="." position="inside">
        <script type="text/javascript" src="/my_library/ static/tests/my_library_tour.js" />
    </xpath>
</template>
  1. 添加一个/tests/test_tour.py文件,通过HttpCase运行tour,如下所示:
from odoo.tests.common
import HttpCase, tagged class TestBookUI(HttpCase):
    @tagged('post_install', '-at_install') 
    def test_01_book_tour(self):
    """Books UI tour test case"""
    self.browser_js("/web",
        "odoo.__DEBUG__.services['web_tour.tour']. run('library_tour')",
        "odoo.__DEBUG__.services['web_tour.tour']. tours.library_tour.ready",
        login = "admin")

运行测试用例

./odoo-bin -c server.conf -i my_library --test-enable

运行日志如下:

...INFO test odoo.addons.my_library.tests.test_tour.TestBookUI: console log: Tour library_tour succeeded

原理

为了创建tour测试用例,您需要首先创建UI tour。如果你想了解更多关于UI tours的信息,请参考第15章“Web客户端开发”中的通过向导提升交互感一节。
步骤1,我们用library_tour注册了一个新的tour。
步骤2,我们为向导测试用例添加了步骤。
与之前的向导案例相比,这里有两个主要变化。首先,我们为向导定义添加了一个test=true参数;其次,我们添加了一个额外的属性,run。在run函数中,您必须编写逻辑来执行通常由用户执行的操作。例如,在向导的第四步中,我们要求用户输入书名。
为了自动化这个步骤,我们添加了一个run函数来设置title字段中的值。run函数将操作实用程序作为参数传递。这提供了一些执行基本操作的快捷方式。最重要的问题如下:

  • actions.click(element): 点击元素
  • actions.dblclick(element): 双击元素
  • actions.tripleclick(element): 三击元素
  • actions.text(string): 设置input的值
  • actions.drag_and_drop(to, element):拖放元素
  • actions.keydown(keyCodes, element): 在元素上触发特定的按键事件
  • actions.auto(): 默认动作。当在tour步骤中没有传递run函数时,将执行actions.auto()。这通常会单击步骤中触发的元素。这里唯一的例外是输入元素。如果触发的是input,那么tour将在输入中设置默认值Test。这就是为什么我们不需要向所有步骤添加run函数。
    另外,如果默认操作不够,您也可以手动执行整个操作。在下一个步骤中,我们想要为颜色选择器设置一个值。注意,我们使用的是手动操作,因为默认值在这里不起作用。因此,我们使用基本的jQuery代码添加了run方法来单击颜色选择器的第三个颜色圆点。在这里,可通过this.$archor属性获取需触发的元素。
    默认情况下,注册的向导将提高终端用户的交互体验。为了测试它们,你需要在Headless Chrome中运行它们。为此,您需要使用HttpCase触发测试用例。这提供了browser_ js方法,该方法打开URL并执行作为第二个参数传递的命令。如下所示:
odoo.__DEBUG__.services['web_tour.tour'].run('library_tour')

在我们的示例中,向导测试用例的名称将作为browser_js的第一个参数。随后的参数待执行的测试用用例,最后一个参数是执行测试用例用户名。

运行客户端侧的测试用用例

odoo提供了通过UI运行客户端测试用例的方法,我们可以看到测试用例每一步的执行情况。

步骤

我们可以通过UI运行QUit和向导测试用例。我们可以激活开发者模式,查看通过UI执行的选项。

通过UI运行QUit测试用例

点击BUG图标,选择Run JS Tests,如下:

这会打开QUit实例,并逐个运行测试用例,如下图。默认,仅展示测试失败的用例。如果想显示所有的测试用例,取消Hide passed tests选项。

通过UI运行向导测试

点击BUG图标,选择Start Tour,如下:

将展示向导测试用例的列表,我们可点击后面的start启动相应的测试用例:

如果您启用了测试资产模式,那么测试之旅只会显示在列表中。如果在列表中没有找到library_tour,请确保已激活测试资产模式。

原理

QUnit的UI是由QUnit框架本身提供的。在这里,您可以为模块筛选测试用例。您甚至可以为一个模块运行一个测试用例。通过UI,您可以看到每个测试用例的进度,并且可以深入到测试用例的每个步骤。在内部,Odoo只是在Headless Chrome打开相同的URL。
点击Run tours选项将显示可用的tours列表。通过点击列表上的播放按钮,您可以运行向导测试用例。注意,当向导通过命令行选项运行时,它将在回滚事务中运行,因此在向导成功后,通过向导所做的更改将被回滚。但是,当tour从UI运行时,它的工作方式就像用户正在操作它一样,这意味着tour所做的更改不会回滚并停留在那里,所以要小心使用这个选项。

调试测试端侧的测试用例

开发复杂的客户端测试用例是件非常头痛的事。本节,我们将学习如何调试客户端测试用例,如何运行其中一个测试用例。

准备

步骤

  1. 用QUit.onlg替换/static/tests/colorpicker_tests.js中的QUit.test测试方法:
QUnit.only('int_color field test cases', function (assert) {
  1. 在createView中添加debug参数如下:
var form = testUtils.createView({ 
	View: FormView,
	model: 'book',
	data: this.data,
	arch: '<form string="Books">' +
		'<group>' +
		'<field name="name"/>' +
		'<field name="color" widget="int_color"/>' +
		'</group>' +
		'</form>', 
	res_id: 1,
	debug:true
});

点击 Run JS Tests:

原理

步骤1,我们用QUnit.only替换了QUnit.test。这将只运行这个测试用例。在测试用例的开发过程中,这可以节省时间。注意,使用QUnit.only将会终止通过命令行选项运行的测试用例。这只能用于调试或测试,并且只能在从UI打开测试用例时使用,所以不要忘记在开发完成后将其替换为QUnit.test。
在我们的QUnit测试用例示例中,我们创建了表单视图来测试int_ color小部件。如果您在UI中运行QUnit测试用例,您将了解到您不能在UI中看到创建的表单视图。在QUnit套件的UI中,您只能看到日志。这使得开发QUnit测试用例非常困难。为了解决这个问题,在createView函数中使用了debug参数。在步骤2中,我们在createView函数中添加了debug: true。这将在浏览器中显示test form视图。在这里,您可以通过浏览器调试器定位文档对象模型(Document Object Model, DOM)元素。

警告
在测试用例的最后,我们通过destroy()方法销毁视图。如果您已经销毁了视图,那么您将无法在UI中看到表单视图,因此为了在浏览器中看到它,请在开发期间删除这一行。这将帮助您调试测试用例。

为失败的测试用例生成视频或屏幕截图

Odoo使用headless CHrome。这开启了新的可能性。从Odoo 12开始,您可以录制失败的测试用例的视频,也可以对失败的测试用例进行截屏。

步骤

为测试用例录制视频需要一个ffmpeg包。

  1. 安装包
apt-get install ffmpeg
  1. 要生成视频或屏幕截图,您需要提供一个目录位置来存储视频或屏幕截图。
  2. 如果你想生成一个测试用例的截屏(视频),使用——截屏命令,如下:
./odoo-bin -c server.conf -i my_library --test-enable --screencasts=/home/pga/odoo_test/
  1. 如果你想生成一个测试用例的截图,使用——screenshosts命令,如下:
./odoo-bin -c server.conf -i my_library --test-enable --screenshots=/home/pga/odoo_test/

原理

为了为失败的测试案例生成截屏/截屏,您需要使用保存视频或图像文件的路径运行服务器。当您运行测试用例时,如果测试用例失败了,Odoo将在给定目录中保存失败测试用例的截图/视频。
为了生成测试用例的视频,Odoo使用了ffmpeg包。如果您没有在服务器上安装这个包,那么它将只保存一个失败的测试用例的截图。在安装这个包之后,您将能够看到任何失败的测试用例的mp4文件。

小贴士
为测试用例生成视频会占用磁盘上更多的空间,所以请谨慎使用此选项,并且只在确实需要时使用。

请记住,屏幕截图和视频只会为失败的测试用例生成,所以如果您想要测试它们,您需要编写一个失败的测试用例。

为测试填充随机数据

到目前为止,我们已经看到了用于检测业务逻辑中的错误或bug的测试用例。然而,有时我们需要用大量的数据来测试我们的开发。生成大量数据可能是一项乏味的工作。Odoo提供了一套工具,可以帮助您为模型生成大量随机数据。在本节,我们将使用populate命令为library.book模型生成测试数据。

准备

对于本节,我们将继续使用上一节的my_library模块。我们将添加_populate_factories方法,它将用于生成测试数据。

步骤

  1. 在my_library模块中添加populate文件夹,添加__init__.py文件。
from . import library_data
  1. 添加my_library/populate/library_data.py文件:
from odoo import models
from odoo.tools import populate


class BookData(models.Model):
    _inherit = "library.book"
    _populate_sizes = {"small": 10, "medium": 100, "large": 500}

    def _populate_factories(self):
        return [
            ("name", populate.constant("Book no {counter}")),
        ]
  1. 运行命令
./odoo-bin populate -–models=library.book –-size=medium -c server.conf -i my_library

这将为图书生成100个单位的数据。生成数据后,流程将被终止。要查看该书的数据,运行不带填充参数的命令。

原理

步骤1,新增生成数据文件目录。
步骤2,添加生成数据代码。使用populate_factories生成随机数据。_populate_factories方法返回模型字段的工厂,这些工厂将用于生成随机数据。模型具有必需的name字段,因此在我们的示例中,我们返回了name字段的生成器。这个生成器将用于为图书记录生成随机数据。我们已经使用了populate.constant;当我们在数据生成过程中进行迭代时,这将生成不同的名称。
除了populate.constant,Odoo提供了其他几个生成器来填充数据,如下:

  • populate.randomize(list):从给定的列表返回随机元素
  • populate.cartesian(list): 与randomize类似,但尽可能保所列表中所有的内容。
  • populate.constant(str): 用于生成格式化字符串。还可以传递formatter参数来格式化值。默认情况下,格式化程序是一个字符串格式函数。
  • populate.compute(function): 当您想要根据您的函数计算一个值时使用。
  • populate.randint(a, b): 用于在a和b参数之间生成一个随机数。

另一个重要的属性是_populate_sizes。基于--size参数,表示想要生成的数据的数量。
步骤3,我们生成了图书的模型。为了生成测试数据,我们需要使用--size和--model参数。odoo将使用_populate方法生成随机记录。_populate方法调用_populate_factories方法生成随机数据。

小贴士
如果多次运行populate命令,数据也将生成多次。小心使用这一点非常重要:如果在生产数据库中运行该命令,它将在生产数据库中生成测试数据。这是你要避免的。

更多

有时,您也希望生成关系数据。例如,对于书籍,您可能还希望创建作者或租借记录。要管理这样的记录,可以使用_populate_dependencies属性:

class BookData(models.Model):
	_inherit = 'library.book'
	_populate_sizes = {'small': 10, 'medium': 100, 'large': 500}
	_populate_dependencies = ['res.users', 'res.company']

这将在填充当前模型之前填充依赖项数据。一旦完成,你可以通过populated_models注册表访问已填充的数据:

company_ids = self.env.registry.populated_models['res.company']

这里给出的行将为您提供在为当前模型生成测试数据之前填充的公司列表。

posted @ 2021-03-12 23:07  老韩头的开发日常  阅读(1178)  评论(0编辑  收藏  举报