Издеваться в среде Odoo? - PullRequest
       8

Издеваться в среде Odoo?

0 голосов
/ 04 сентября 2018

Кто-нибудь знает, как написать фиктивные тесты для объектов Odoo?

У меня есть следующие классы и методы:

my_module

from odoo import models


class MyModel(models.Model):

    _name = 'my.model'

    def action_copy(self):
        IrTranslation = self.env['ir.translation']
        for rec in self:
            if rec.translate:
                IrTranslation.force_translation(rec)

my_module_2 :

from odoo import models


class IrTranslation(models.Model):
    _inherit = 'ir.translation'

    def force_translation(self, rec):
        # do stuff

Когда я вызываю его, я хочу проверить, был ли IrTranslation.force_translation вызван в методе action_copy и сколько раз.

Но этот метод не импортируется напрямую, на него ссылаются через env.

Если, скажем, force_translation будет импортировано как:

from my_module_2.IrTranslation import force_translation

def action_copy(self):
    # do stuff.
    force_translation()

Тогда я мог бы попытаться сделать что-то вроде этого:

from unittest import mock
from my_module import action_copy

 def test_some_1(self):
        with mock.patch('my_module.my_module_2.IrTranslation') as mocked_translation:
            action_copy()
            mocked_translation.force_translation.assert_called_once()

Но так как модули в Odoo не импортируются напрямую (как вы делаете это в простом Python), я не понимаю, как указывать методы в среде Odoo для имитации.

P.S. Я также не видел никаких поддельных тестов в стандартном Odoo, за исключением базовых классов, которые не наследуют Model class ->, которые затем нужно использовать его атрибут _inherit вместо импорта класса и передачи его для наследования другому классу. .

Ответы [ 2 ]

0 голосов
/ 05 июля 2019

Это можно сделать. Я делаю это все время, начиная с Odoo 8.0 (до 12.0 сейчас). Ключ должен знать, куда патчить, но я не могу придумать четкого правила для этого, потому что Odoo делает трюки с именем вашего пакета, когда он импортирует ваш модуль. Так что в вашем случае вы можете сделать следующее:

from odoo import tests
from mock import patch
from my_module_2.models.ir_translations import IrTranslation


class TestMyModule2(tests.TransactionCase):
    def some_test_1(self):
        my_model = self.env['my.model'].create({})

        with patch.object(IrTranslation, 'force_translation') as mocked_translation:
            my_model.action_copy()

        mocked_translation.assert_called_once()

Или исправление с использованием Python type() (тогда нет необходимости импортировать класс):

with patch.object(type(self.env['ir.translation']), 'force_translation') as mocked_translation:
    my_model.action_copy()

Это работает большую часть времени. Если патч не работает, вам может понадобиться импортировать класс, используя относительный импорт:

from ..models.ir_translations import IrTranslation

Если это по-прежнему не работает, вам может потребоваться установить исправление в методе setUp():

from odoo import tests
from mock import patch
from my_module_2.models.ir_translations import IrTranslation


class TestMyModule2(tests.TransactionCase):
    def setUp(self):
        super().setUp()  # don't forget this
        self._mocked_translation = patch.object(IrTranslation, 'force_translation').start()
        self.addCleanup(patch.stopall)

    def some_test_1(self):
        my_model = self.env['my.model'].create({})

        my_model.action_copy()

        self._mocked_translation.assert_called_once()

Некоторые дополнительные заметки, чтобы избавить вас от головной боли:

  • Если вы используете pyCharm, не насмехайтесь над socket объектами. Это портит Механизмы pyCharm. Лучше поместить ваши звонки в сокет в одну строку метод и вместо этого смоделируйте этот метод.
  • datetime.datetime.now() нельзя смоделировать, как все встроенные типы, но fields.Datetime.now() может.
0 голосов
/ 04 сентября 2018

Тестирование в Odoo не использует концепцию насмешек. Вместо этого тесты выводятся из стандартных базовых классов. Стандартный класс TransactionalTest открывает транзакцию и никогда не фиксирует ее, но откатывает, чтобы отменить любые изменения.

Это, очевидно, не то же самое, что обычное моделирование, в котором вы не можете заменить другие методы или классы для возврата фиксированных / ожидаемых значений и / или избежать других побочных эффектов, кроме постоянных изменений в базе данных, таких как отправка электронных писем или вызов удаленный веб-сервис.

...