changeset b777fb7b5121 in modules/product:default
details: https://hg.tryton.org/modules/product?cmd=changeset&node=b777fb7b5121
description:
Replace test setuptools command by unittest discover
issue9215
review389851002
diffstat:
setup.py | 6 +-
tests/__init__.py | 7 -
tests/test_module.py | 502 +++++++++++++++++++++++++++++++++++++++++++++++
tests/test_product.py | 520 -------------------------------------------------
tests/test_scenario.py | 22 ++
tox.ini | 3 +-
6 files changed, 529 insertions(+), 531 deletions(-)
diffs (1103 lines):
diff -r e9312a4a1bf1 -r b777fb7b5121 setup.py
--- a/setup.py Mon Apr 11 23:24:21 2022 +0200
+++ b/setup.py Sat Apr 16 18:30:17 2022 +0200
@@ -141,13 +141,13 @@
license='GPL-3',
python_requires='>=3.7',
install_requires=requires,
+ extras_require={
+ 'test': tests_require,
+ },
dependency_links=dependency_links,
zip_safe=False,
entry_points="""
[trytond.modules]
product = trytond.modules.product
""",
- test_suite='tests',
- test_loader='trytond.test_loader:Loader',
- tests_require=tests_require,
)
diff -r e9312a4a1bf1 -r b777fb7b5121 tests/__init__.py
--- a/tests/__init__.py Mon Apr 11 23:24:21 2022 +0200
+++ b/tests/__init__.py Sat Apr 16 18:30:17 2022 +0200
@@ -1,9 +1,2 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
-
-try:
- from trytond.modules.product.tests.test_product import suite
-except ImportError:
- from .test_product import suite
-
-__all__ = ['suite']
diff -r e9312a4a1bf1 -r b777fb7b5121 tests/test_module.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test_module.py Sat Apr 16 18:30:17 2022 +0200
@@ -0,0 +1,502 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from decimal import Decimal
+
+from trytond.modules.company.tests import CompanyTestMixin
+from trytond.modules.product import round_price
+from trytond.modules.product.exceptions import UOMAccessError
+from trytond.pool import Pool
+from trytond.tests.test_tryton import ModuleTestCase, with_transaction
+from trytond.transaction import Transaction
+
+
+class ProductTestCase(CompanyTestMixin, ModuleTestCase):
+ 'Test Product module'
+ module = 'product'
+
+ @with_transaction()
+ def test_uom_non_zero_rate_factor(self):
+ 'Test uom non_zero_rate_factor constraint'
+ pool = Pool()
+ UomCategory = pool.get('product.uom.category')
+ Uom = pool.get('product.uom')
+ transaction = Transaction()
+ category, = UomCategory.create([{'name': 'Test'}])
+
+ self.assertRaises(Exception, Uom.create, [{
+ 'name': 'Test',
+ 'symbol': 'T',
+ 'category': category.id,
+ 'rate': 0,
+ 'factor': 0,
+ }])
+ transaction.rollback()
+
+ def create():
+ category, = UomCategory.create([{'name': 'Test'}])
+ return Uom.create([{
+ 'name': 'Test',
+ 'symbol': 'T',
+ 'category': category.id,
+ 'rate': 1.0,
+ 'factor': 1.0,
+ }])[0]
+
+ uom = create()
+ self.assertRaises(Exception, Uom.write, [uom], {
+ 'rate': 0.0,
+ })
+ transaction.rollback()
+
+ uom = create()
+ self.assertRaises(Exception, Uom.write, [uom], {
+ 'factor': 0.0,
+ })
+ transaction.rollback()
+
+ uom = create()
+ self.assertRaises(Exception, Uom.write, [uom], {
+ 'rate': 0.0,
+ 'factor': 0.0,
+ })
+ transaction.rollback()
+
+ @with_transaction()
+ def test_uom_check_factor_and_rate(self):
+ 'Test uom check_factor_and_rate constraint'
+ pool = Pool()
+ UomCategory = pool.get('product.uom.category')
+ Uom = pool.get('product.uom')
+ transaction = Transaction()
+ category, = UomCategory.create([{'name': 'Test'}])
+
+ self.assertRaises(Exception, Uom.create, [{
+ 'name': 'Test',
+ 'symbol': 'T',
+ 'category': category.id,
+ 'rate': 2,
+ 'factor': 2,
+ }])
+ transaction.rollback()
+
+ def create():
+ category, = UomCategory.create([{'name': 'Test'}])
+ return Uom.create([{
+ 'name': 'Test',
+ 'symbol': 'T',
+ 'category': category.id,
+ 'rate': 1.0,
+ 'factor': 1.0,
+ }])[0]
+
+ uom = create()
+ self.assertRaises(Exception, Uom.write, [uom], {
+ 'rate': 2.0,
+ })
+ transaction.rollback()
+
+ uom = create()
+ self.assertRaises(Exception, Uom.write, [uom], {
+ 'factor': 2.0,
+ })
+ transaction.rollback()
+
+ @with_transaction()
+ def test_uom_select_accurate_field(self):
+ 'Test uom select_accurate_field function'
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ tests = [
+ ('Meter', 'factor'),
+ ('Kilometer', 'factor'),
+ ('Centimeter', 'rate'),
+ ('Foot', 'factor'),
+ ]
+ for name, result in tests:
+ uom, = Uom.search([
+ ('name', '=', name),
+ ], limit=1)
+ self.assertEqual(result, uom.accurate_field)
+
+ @with_transaction()
+ def test_uom_compute_qty(self):
+ 'Test uom compute_qty function'
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ tests = [
+ ('Kilogram', 100, 'Gram', 100000, 100000),
+ ('Gram', 1, 'Pound', 0.0022046226218487759, 0.0),
+ ('Second', 5, 'Minute', 0.083333333333333343, 0.08),
+ ('Second', 25, 'Hour', 0.0069444444444444441, 0.01),
+ ('Millimeter', 3, 'Inch', 0.11811023622047245, 0.12),
+ ('Millimeter', 0, 'Inch', 0, 0),
+ ('Millimeter', None, 'Inch', None, None),
+ ]
+ for from_name, qty, to_name, result, rounded_result in tests:
+ from_uom, = Uom.search([
+ ('name', '=', from_name),
+ ], limit=1)
+ to_uom, = Uom.search([
+ ('name', '=', to_name),
+ ], limit=1)
+ self.assertEqual(result, Uom.compute_qty(
+ from_uom, qty, to_uom, False))
+ self.assertEqual(rounded_result, Uom.compute_qty(
+ from_uom, qty, to_uom, True))
+ self.assertEqual(0.2, Uom.compute_qty(None, 0.2, None, False))
+ self.assertEqual(0.2, Uom.compute_qty(None, 0.2, None, True))
+
+ tests_exceptions = [
+ ('Millimeter', 3, 'Pound', ValueError),
+ ('Kilogram', 'not a number', 'Pound', TypeError),
+ ]
+ for from_name, qty, to_name, exception in tests_exceptions:
+ from_uom, = Uom.search([
+ ('name', '=', from_name),
+ ], limit=1)
+ to_uom, = Uom.search([
+ ('name', '=', to_name),
+ ], limit=1)
+ self.assertRaises(exception, Uom.compute_qty,
+ from_uom, qty, to_uom, False)
+ self.assertRaises(exception, Uom.compute_qty,
+ from_uom, qty, to_uom, True)
+ self.assertRaises(ValueError, Uom.compute_qty,
+ None, qty, to_uom, True)
+ self.assertRaises(ValueError, Uom.compute_qty,
+ from_uom, qty, None, True)
+
+ @with_transaction()
+ def test_uom_compute_qty_category(self):
+ "Test uom compute_qty with different category"
+ pool = Pool()
+ Uom = pool.get('product.uom')
+
+ g, = Uom.search([
+ ('name', '=', "Gram"),
+ ], limit=1)
+ m3, = Uom.search([
+ ('name', '=', "Cubic meter"),
+ ], limit=1)
+
+ for quantity, result, keys in [
+ (10000, 0.02, dict(factor=2)),
+ (20000, 0.01, dict(rate=2)),
+ (30000, 0.01, dict(rate=3, factor=0.333333, round=False)),
+ ]:
+ msg = 'quantity: %r, keys: %r' % (quantity, keys)
+ self.assertEqual(
+ Uom.compute_qty(g, quantity, m3, **keys), result,
+ msg=msg)
+
+ @with_transaction()
+ def test_uom_compute_price(self):
+ 'Test uom compute_price function'
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ tests = [
+ ('Kilogram', Decimal('100'), 'Gram', Decimal('0.1')),
+ ('Gram', Decimal('1'), 'Pound', Decimal('453.59237')),
+ ('Second', Decimal('5'), 'Minute', Decimal('300')),
+ ('Second', Decimal('25'), 'Hour', Decimal('90000')),
+ ('Millimeter', Decimal('3'), 'Inch', Decimal('76.2')),
+ ('Millimeter', Decimal('0'), 'Inch', Decimal('0')),
+ ('Millimeter', None, 'Inch', None),
+ ]
+ for from_name, price, to_name, result in tests:
+ from_uom, = Uom.search([
+ ('name', '=', from_name),
+ ], limit=1)
+ to_uom, = Uom.search([
+ ('name', '=', to_name),
+ ], limit=1)
+ self.assertEqual(result, Uom.compute_price(
+ from_uom, price, to_uom))
+ self.assertEqual(Decimal('0.2'), Uom.compute_price(
+ None, Decimal('0.2'), None))
+
+ tests_exceptions = [
+ ('Millimeter', Decimal('3'), 'Pound', ValueError),
+ ('Kilogram', 'not a number', 'Pound', TypeError),
+ ]
+ for from_name, price, to_name, exception in tests_exceptions:
+ from_uom, = Uom.search([
+ ('name', '=', from_name),
+ ], limit=1)
+ to_uom, = Uom.search([
+ ('name', '=', to_name),
+ ], limit=1)
+ self.assertRaises(exception, Uom.compute_price,
+ from_uom, price, to_uom)
+ self.assertRaises(ValueError, Uom.compute_price,
+ None, price, to_uom)
+ self.assertRaises(ValueError, Uom.compute_price,
+ from_uom, price, None)
+
+ @with_transaction()
+ def test_uom_compute_price_category(self):
+ "Test uom compute_price with different category"
+ pool = Pool()
+ Uom = pool.get('product.uom')
+
+ g, = Uom.search([
+ ('name', '=', "Gram"),
+ ], limit=1)
+ m3, = Uom.search([
+ ('name', '=', "Cubic meter"),
+ ], limit=1)
+
+ for price, result, keys in [
+ (Decimal('0.001'), Decimal('500'), dict(factor=2)),
+ (Decimal('0.002'), Decimal('4000'), dict(rate=2)),
+ (Decimal('0.003'), Decimal('9000'), dict(
+ rate=3, factor=0.333333)),
+ ]:
+ msg = 'price: %r, keys: %r' % (price, keys)
+ self.assertEqual(
+ Uom.compute_price(g, price, m3, **keys), result,
+ msg=msg)
+
+ @with_transaction()
+ def test_uom_modify_factor_rate(self):
+ "Test can not modify factor or rate of uom"
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ g, = Uom.search([('name', '=', "Gram")])
+
+ g.factor = 1
+ g.rate = 1
+
+ with self.assertRaises(UOMAccessError):
+ g.save()
+
+ @with_transaction()
+ def test_uom_modify_category(self):
+ "Test can not modify category of uom"
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ Category = pool.get('product.uom.category')
+ g, = Uom.search([('name', '=', "Gram")])
+ units, = Category.search([('name', '=', "Units")])
+
+ g.category = units
+
+ with self.assertRaises(UOMAccessError):
+ g.save()
+
+ @with_transaction()
+ def test_uom_increase_digits(self):
+ "Test can increase digits of uom"
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ g, = Uom.search([('name', '=', "Gram")])
+
+ g.digits += 1
+
+ g.save()
+
+ @with_transaction()
+ def test_uom_decrease_digits(self):
+ "Test can not decrease digits of uom"
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ g, = Uom.search([('name', '=', "Gram")])
+
+ g.digits -= 1
+ g.rounding = 1
+
+ with self.assertRaises(UOMAccessError):
+ g.save()
+
+ @with_transaction()
+ def test_product_search_domain(self):
+ 'Test product.product search_domain function'
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ Template = pool.get('product.template')
+ Product = pool.get('product.product')
+
+ kilogram, = Uom.search([
+ ('name', '=', 'Kilogram'),
+ ], limit=1)
+ millimeter, = Uom.search([
+ ('name', '=', 'Millimeter'),
+ ])
+ pt1, pt2 = Template.create([{
+ 'name': 'P1',
+ 'type': 'goods',
+ 'default_uom': kilogram.id,
+ 'products': [('create', [{
+ 'code': '1',
+ }])]
+ }, {
+ 'name': 'P2',
+ 'type': 'goods',
+ 'default_uom': millimeter.id,
+ 'products': [('create', [{
+ 'code': '2',
+ }])]
+ }])
+ p, = Product.search([
+ ('default_uom.name', '=', 'Kilogram'),
+ ])
+ self.assertEqual(p, pt1.products[0])
+ p, = Product.search([
+ ('default_uom.name', '=', 'Millimeter'),
+ ])
+ self.assertEqual(p, pt2.products[0])
+
+ @with_transaction()
+ def test_search_domain_conversion(self):
+ 'Test the search domain conversion'
+ pool = Pool()
+ Category = pool.get('product.category')
+ Template = pool.get('product.template')
+ Product = pool.get('product.product')
+ Uom = pool.get('product.uom')
+
+ category1, = Category.create([{'name': 'Category1'}])
+ category2, = Category.create([{'name': 'Category2'}])
+ uom, = Uom.search([], limit=1)
+ values1 = {
+ 'name': 'Some product-1',
+ 'categories': [('add', [category1.id])],
+ 'type': 'goods',
+ 'default_uom': uom.id,
+ 'products': [('create', [{}])],
+ }
+ values2 = {
+ 'name': 'Some product-2',
+ 'categories': [('add', [category2.id])],
+ 'type': 'goods',
+ 'default_uom': uom.id,
+ 'products': [('create', [{}])],
+ }
+
+ # This is a false positive as there is 1 product with the
+ # template 1 and the same product with category 1. If you do not
+ # create two categories (or any other relation on the template
+ # model) you wont be able to check as in most cases the
+ # id of the template and the related model would be same (1).
+ # So two products have been created with same category. So that
+ # domain ('template.categories', '=', 1) will return 2 records which
+ # it supposed to be.
+ template1, template2, template3, template4 = Template.create(
+ [values1, values1.copy(), values2, values2.copy()]
+ )
+ self.assertEqual(Product.search([], count=True), 4)
+ self.assertEqual(
+ Product.search([
+ ('categories', '=', category1.id),
+ ], count=True), 2)
+
+ self.assertEqual(
+ Product.search([
+ ('template.categories', '=', category1.id),
+ ], count=True), 2)
+
+ self.assertEqual(
+ Product.search([
+ ('categories', '=', category2.id),
+ ], count=True), 2)
+ self.assertEqual(
+ Product.search([
+ ('template.categories', '=', category2.id),
+ ], count=True), 2)
+
+ @with_transaction()
+ def test_uom_rounding(self):
+ 'Test uom rounding functions'
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ tests = [
+ (2.53, .1, 2.5, 2.6, 2.5),
+ (3.8, .1, 3.8, 3.8, 3.8),
+ (3.7, .1, 3.7, 3.7, 3.7),
+ (1.3, .5, 1.5, 1.5, 1.0),
+ (1.1, .3, 1.2, 1.2, 0.9),
+ (17, 10, 20, 20, 10),
+ (7, 10, 10, 10, 0),
+ (4, 10, 0, 10, 0),
+ (17, 15, 15, 30, 15),
+ (2.5, 1.4, 2.8, 2.8, 1.4),
+ ]
+ for number, precision, round, ceil, floor in tests:
+ uom = Uom(rounding=precision)
+ self.assertEqual(uom.round(number), round)
+ self.assertEqual(uom.ceil(number), ceil)
+ self.assertEqual(uom.floor(number), floor)
+
+ @with_transaction()
+ def test_product_order(self):
+ 'Test product field order'
+ pool = Pool()
+ Template = pool.get('product.template')
+ Product = pool.get('product.product')
+ Uom = pool.get('product.uom')
+
+ uom, = Uom.search([], limit=1)
+ values1 = {
+ 'name': 'Product A',
+ 'type': 'assets',
+ 'default_uom': uom.id,
+ 'products': [('create', [{'suffix_code': 'AA'}])],
+ }
+ values2 = {
+ 'name': 'Product B',
+ 'type': 'goods',
+ 'default_uom': uom.id,
+ 'products': [('create', [{'suffix_code': 'BB'}])],
+ }
+
+ template1, template2 = Template.create([values1, values2])
+ product1, product2 = Product.search([])
+
+ # Non-inherited field.
+ self.assertEqual(
+ Product.search([], order=[('code', 'ASC')]), [product1, product2])
+ self.assertEqual(
+ Product.search([], order=[('code', 'DESC')]), [product2, product1])
+ self.assertEqual(Product.search(
+ [('name', 'like', '%')], order=[('code', 'ASC')]),
+ [product1, product2])
+ self.assertEqual(Product.search(
+ [('name', 'like', '%')], order=[('code', 'DESC')]),
+ [product2, product1])
+
+ # Inherited field with custom order.
+ self.assertEqual(
+ Product.search([], order=[('name', 'ASC')]), [product1, product2])
+ self.assertEqual(
+ Product.search([], order=[('name', 'DESC')]), [product2, product1])
+ self.assertEqual(Product.search(
+ [('name', 'like', '%')], order=[('name', 'ASC')]),
+ [product1, product2])
+ self.assertEqual(Product.search(
+ [('name', 'like', '%')], order=[('name', 'DESC')]),
+ [product2, product1])
+
+ # Inherited field without custom order.
+ self.assertEqual(
+ Product.search([], order=[('type', 'ASC')]), [product1, product2])
+ self.assertEqual(
+ Product.search([], order=[('type', 'DESC')]), [product2, product1])
+ self.assertEqual(Product.search(
+ [('name', 'like', '%')], order=[('type', 'ASC')]),
+ [product1, product2])
+ self.assertEqual(Product.search(
+ [('name', 'like', '%')], order=[('type', 'DESC')]),
+ [product2, product1])
+
+ def test_round_price(self):
+ for value, result in [
+ (Decimal('1'), Decimal('1.0000')),
+ (Decimal('1.12345'), Decimal('1.1234')),
+ (1, Decimal('1')),
+ ]:
+ with self.subTest(value=value):
+ self.assertEqual(round_price(value), result)
+
+
+del ModuleTestCase
diff -r e9312a4a1bf1 -r b777fb7b5121 tests/test_product.py
--- a/tests/test_product.py Mon Apr 11 23:24:21 2022 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,520 +0,0 @@
-# This file is part of Tryton. The COPYRIGHT file at the top level of
-# this repository contains the full copyright notices and license terms.
-import doctest
-import unittest
-from decimal import Decimal
-
-import trytond.tests.test_tryton
-from trytond.modules.company.tests import CompanyTestMixin
-from trytond.pool import Pool
-from trytond.tests.test_tryton import (
- ModuleTestCase, doctest_checker, doctest_teardown, with_transaction)
-from trytond.transaction import Transaction
-
-from ..exceptions import UOMAccessError
-from ..product import round_price
-
-
-class ProductTestCase(CompanyTestMixin, ModuleTestCase):
- 'Test Product module'
- module = 'product'
-
- @with_transaction()
- def test_uom_non_zero_rate_factor(self):
- 'Test uom non_zero_rate_factor constraint'
- pool = Pool()
- UomCategory = pool.get('product.uom.category')
- Uom = pool.get('product.uom')
- transaction = Transaction()
- category, = UomCategory.create([{'name': 'Test'}])
-
- self.assertRaises(Exception, Uom.create, [{
- 'name': 'Test',
- 'symbol': 'T',
- 'category': category.id,
- 'rate': 0,
- 'factor': 0,
- }])
- transaction.rollback()
-
- def create():
- category, = UomCategory.create([{'name': 'Test'}])
- return Uom.create([{
- 'name': 'Test',
- 'symbol': 'T',
- 'category': category.id,
- 'rate': 1.0,
- 'factor': 1.0,
- }])[0]
-
- uom = create()
- self.assertRaises(Exception, Uom.write, [uom], {
- 'rate': 0.0,
- })
- transaction.rollback()
-
- uom = create()
- self.assertRaises(Exception, Uom.write, [uom], {
- 'factor': 0.0,
- })
- transaction.rollback()
-
- uom = create()
- self.assertRaises(Exception, Uom.write, [uom], {
- 'rate': 0.0,
- 'factor': 0.0,
- })
- transaction.rollback()
-
- @with_transaction()
- def test_uom_check_factor_and_rate(self):
- 'Test uom check_factor_and_rate constraint'
- pool = Pool()
- UomCategory = pool.get('product.uom.category')
- Uom = pool.get('product.uom')
- transaction = Transaction()
- category, = UomCategory.create([{'name': 'Test'}])
-
- self.assertRaises(Exception, Uom.create, [{
- 'name': 'Test',
- 'symbol': 'T',
- 'category': category.id,
- 'rate': 2,
- 'factor': 2,
- }])
- transaction.rollback()
-
- def create():
- category, = UomCategory.create([{'name': 'Test'}])
- return Uom.create([{
- 'name': 'Test',
- 'symbol': 'T',
- 'category': category.id,
- 'rate': 1.0,
- 'factor': 1.0,
- }])[0]
-
- uom = create()
- self.assertRaises(Exception, Uom.write, [uom], {
- 'rate': 2.0,
- })
- transaction.rollback()
-
- uom = create()
- self.assertRaises(Exception, Uom.write, [uom], {
- 'factor': 2.0,
- })
- transaction.rollback()
-
- @with_transaction()
- def test_uom_select_accurate_field(self):
- 'Test uom select_accurate_field function'
- pool = Pool()
- Uom = pool.get('product.uom')
- tests = [
- ('Meter', 'factor'),
- ('Kilometer', 'factor'),
- ('Centimeter', 'rate'),
- ('Foot', 'factor'),
- ]
- for name, result in tests:
- uom, = Uom.search([
- ('name', '=', name),
- ], limit=1)
- self.assertEqual(result, uom.accurate_field)
-
- @with_transaction()
- def test_uom_compute_qty(self):
- 'Test uom compute_qty function'
- pool = Pool()
- Uom = pool.get('product.uom')
- tests = [
- ('Kilogram', 100, 'Gram', 100000, 100000),
- ('Gram', 1, 'Pound', 0.0022046226218487759, 0.0),
- ('Second', 5, 'Minute', 0.083333333333333343, 0.08),
- ('Second', 25, 'Hour', 0.0069444444444444441, 0.01),
- ('Millimeter', 3, 'Inch', 0.11811023622047245, 0.12),
- ('Millimeter', 0, 'Inch', 0, 0),
- ('Millimeter', None, 'Inch', None, None),
- ]
- for from_name, qty, to_name, result, rounded_result in tests:
- from_uom, = Uom.search([
- ('name', '=', from_name),
- ], limit=1)
- to_uom, = Uom.search([
- ('name', '=', to_name),
- ], limit=1)
- self.assertEqual(result, Uom.compute_qty(
- from_uom, qty, to_uom, False))
- self.assertEqual(rounded_result, Uom.compute_qty(
- from_uom, qty, to_uom, True))
- self.assertEqual(0.2, Uom.compute_qty(None, 0.2, None, False))
- self.assertEqual(0.2, Uom.compute_qty(None, 0.2, None, True))
-
- tests_exceptions = [
- ('Millimeter', 3, 'Pound', ValueError),
- ('Kilogram', 'not a number', 'Pound', TypeError),
- ]
- for from_name, qty, to_name, exception in tests_exceptions:
- from_uom, = Uom.search([
- ('name', '=', from_name),
- ], limit=1)
- to_uom, = Uom.search([
- ('name', '=', to_name),
- ], limit=1)
- self.assertRaises(exception, Uom.compute_qty,
- from_uom, qty, to_uom, False)
- self.assertRaises(exception, Uom.compute_qty,
- from_uom, qty, to_uom, True)
- self.assertRaises(ValueError, Uom.compute_qty,
- None, qty, to_uom, True)
- self.assertRaises(ValueError, Uom.compute_qty,
- from_uom, qty, None, True)
-
- @with_transaction()
- def test_uom_compute_qty_category(self):
- "Test uom compute_qty with different category"
- pool = Pool()
- Uom = pool.get('product.uom')
-
- g, = Uom.search([
- ('name', '=', "Gram"),
- ], limit=1)
- m3, = Uom.search([
- ('name', '=', "Cubic meter"),
- ], limit=1)
-
- for quantity, result, keys in [
- (10000, 0.02, dict(factor=2)),
- (20000, 0.01, dict(rate=2)),
- (30000, 0.01, dict(rate=3, factor=0.333333, round=False)),
- ]:
- msg = 'quantity: %r, keys: %r' % (quantity, keys)
- self.assertEqual(
- Uom.compute_qty(g, quantity, m3, **keys), result,
- msg=msg)
-
- @with_transaction()
- def test_uom_compute_price(self):
- 'Test uom compute_price function'
- pool = Pool()
- Uom = pool.get('product.uom')
- tests = [
- ('Kilogram', Decimal('100'), 'Gram', Decimal('0.1')),
- ('Gram', Decimal('1'), 'Pound', Decimal('453.59237')),
- ('Second', Decimal('5'), 'Minute', Decimal('300')),
- ('Second', Decimal('25'), 'Hour', Decimal('90000')),
- ('Millimeter', Decimal('3'), 'Inch', Decimal('76.2')),
- ('Millimeter', Decimal('0'), 'Inch', Decimal('0')),
- ('Millimeter', None, 'Inch', None),
- ]
- for from_name, price, to_name, result in tests:
- from_uom, = Uom.search([
- ('name', '=', from_name),
- ], limit=1)
- to_uom, = Uom.search([
- ('name', '=', to_name),
- ], limit=1)
- self.assertEqual(result, Uom.compute_price(
- from_uom, price, to_uom))
- self.assertEqual(Decimal('0.2'), Uom.compute_price(
- None, Decimal('0.2'), None))
-
- tests_exceptions = [
- ('Millimeter', Decimal('3'), 'Pound', ValueError),
- ('Kilogram', 'not a number', 'Pound', TypeError),
- ]
- for from_name, price, to_name, exception in tests_exceptions:
- from_uom, = Uom.search([
- ('name', '=', from_name),
- ], limit=1)
- to_uom, = Uom.search([
- ('name', '=', to_name),
- ], limit=1)
- self.assertRaises(exception, Uom.compute_price,
- from_uom, price, to_uom)
- self.assertRaises(ValueError, Uom.compute_price,
- None, price, to_uom)
- self.assertRaises(ValueError, Uom.compute_price,
- from_uom, price, None)
-
- @with_transaction()
- def test_uom_compute_price_category(self):
- "Test uom compute_price with different category"
- pool = Pool()
- Uom = pool.get('product.uom')
-
- g, = Uom.search([
- ('name', '=', "Gram"),
- ], limit=1)
- m3, = Uom.search([
- ('name', '=', "Cubic meter"),
- ], limit=1)
-
- for price, result, keys in [
- (Decimal('0.001'), Decimal('500'), dict(factor=2)),
- (Decimal('0.002'), Decimal('4000'), dict(rate=2)),
- (Decimal('0.003'), Decimal('9000'), dict(
- rate=3, factor=0.333333)),
- ]:
- msg = 'price: %r, keys: %r' % (price, keys)
- self.assertEqual(
- Uom.compute_price(g, price, m3, **keys), result,
- msg=msg)
-
- @with_transaction()
- def test_uom_modify_factor_rate(self):
- "Test can not modify factor or rate of uom"
- pool = Pool()
- Uom = pool.get('product.uom')
- g, = Uom.search([('name', '=', "Gram")])
-
- g.factor = 1
- g.rate = 1
-
- with self.assertRaises(UOMAccessError):
- g.save()
-
- @with_transaction()
- def test_uom_modify_category(self):
- "Test can not modify category of uom"
- pool = Pool()
- Uom = pool.get('product.uom')
- Category = pool.get('product.uom.category')
- g, = Uom.search([('name', '=', "Gram")])
- units, = Category.search([('name', '=', "Units")])
-
- g.category = units
-
- with self.assertRaises(UOMAccessError):
- g.save()
-
- @with_transaction()
- def test_uom_increase_digits(self):
- "Test can increase digits of uom"
- pool = Pool()
- Uom = pool.get('product.uom')
- g, = Uom.search([('name', '=', "Gram")])
-
- g.digits += 1
-
- g.save()
-
- @with_transaction()
- def test_uom_decrease_digits(self):
- "Test can not decrease digits of uom"
- pool = Pool()
- Uom = pool.get('product.uom')
- g, = Uom.search([('name', '=', "Gram")])
-
- g.digits -= 1
- g.rounding = 1
-
- with self.assertRaises(UOMAccessError):
- g.save()
-
- @with_transaction()
- def test_product_search_domain(self):
- 'Test product.product search_domain function'
- pool = Pool()
- Uom = pool.get('product.uom')
- Template = pool.get('product.template')
- Product = pool.get('product.product')
-
- kilogram, = Uom.search([
- ('name', '=', 'Kilogram'),
- ], limit=1)
- millimeter, = Uom.search([
- ('name', '=', 'Millimeter'),
- ])
- pt1, pt2 = Template.create([{
- 'name': 'P1',
- 'type': 'goods',
- 'default_uom': kilogram.id,
- 'products': [('create', [{
- 'code': '1',
- }])]
- }, {
- 'name': 'P2',
- 'type': 'goods',
- 'default_uom': millimeter.id,
- 'products': [('create', [{
- 'code': '2',
- }])]
- }])
- p, = Product.search([
- ('default_uom.name', '=', 'Kilogram'),
- ])
- self.assertEqual(p, pt1.products[0])
- p, = Product.search([
- ('default_uom.name', '=', 'Millimeter'),
- ])
- self.assertEqual(p, pt2.products[0])
-
- @with_transaction()
- def test_search_domain_conversion(self):
- 'Test the search domain conversion'
- pool = Pool()
- Category = pool.get('product.category')
- Template = pool.get('product.template')
- Product = pool.get('product.product')
- Uom = pool.get('product.uom')
-
- category1, = Category.create([{'name': 'Category1'}])
- category2, = Category.create([{'name': 'Category2'}])
- uom, = Uom.search([], limit=1)
- values1 = {
- 'name': 'Some product-1',
- 'categories': [('add', [category1.id])],
- 'type': 'goods',
- 'default_uom': uom.id,
- 'products': [('create', [{}])],
- }
- values2 = {
- 'name': 'Some product-2',
- 'categories': [('add', [category2.id])],
- 'type': 'goods',
- 'default_uom': uom.id,
- 'products': [('create', [{}])],
- }
-
- # This is a false positive as there is 1 product with the
- # template 1 and the same product with category 1. If you do not
- # create two categories (or any other relation on the template
- # model) you wont be able to check as in most cases the
- # id of the template and the related model would be same (1).
- # So two products have been created with same category. So that
- # domain ('template.categories', '=', 1) will return 2 records which
- # it supposed to be.
- template1, template2, template3, template4 = Template.create(
- [values1, values1.copy(), values2, values2.copy()]
- )
- self.assertEqual(Product.search([], count=True), 4)
- self.assertEqual(
- Product.search([
- ('categories', '=', category1.id),
- ], count=True), 2)
-
- self.assertEqual(
- Product.search([
- ('template.categories', '=', category1.id),
- ], count=True), 2)
-
- self.assertEqual(
- Product.search([
- ('categories', '=', category2.id),
- ], count=True), 2)
- self.assertEqual(
- Product.search([
- ('template.categories', '=', category2.id),
- ], count=True), 2)
-
- @with_transaction()
- def test_uom_rounding(self):
- 'Test uom rounding functions'
- pool = Pool()
- Uom = pool.get('product.uom')
- tests = [
- (2.53, .1, 2.5, 2.6, 2.5),
- (3.8, .1, 3.8, 3.8, 3.8),
- (3.7, .1, 3.7, 3.7, 3.7),
- (1.3, .5, 1.5, 1.5, 1.0),
- (1.1, .3, 1.2, 1.2, 0.9),
- (17, 10, 20, 20, 10),
- (7, 10, 10, 10, 0),
- (4, 10, 0, 10, 0),
- (17, 15, 15, 30, 15),
- (2.5, 1.4, 2.8, 2.8, 1.4),
- ]
- for number, precision, round, ceil, floor in tests:
- uom = Uom(rounding=precision)
- self.assertEqual(uom.round(number), round)
- self.assertEqual(uom.ceil(number), ceil)
- self.assertEqual(uom.floor(number), floor)
-
- @with_transaction()
- def test_product_order(self):
- 'Test product field order'
- pool = Pool()
- Template = pool.get('product.template')
- Product = pool.get('product.product')
- Uom = pool.get('product.uom')
-
- uom, = Uom.search([], limit=1)
- values1 = {
- 'name': 'Product A',
- 'type': 'assets',
- 'default_uom': uom.id,
- 'products': [('create', [{'suffix_code': 'AA'}])],
- }
- values2 = {
- 'name': 'Product B',
- 'type': 'goods',
- 'default_uom': uom.id,
- 'products': [('create', [{'suffix_code': 'BB'}])],
- }
-
- template1, template2 = Template.create([values1, values2])
- product1, product2 = Product.search([])
-
- # Non-inherited field.
- self.assertEqual(
- Product.search([], order=[('code', 'ASC')]), [product1, product2])
- self.assertEqual(
- Product.search([], order=[('code', 'DESC')]), [product2, product1])
- self.assertEqual(Product.search(
- [('name', 'like', '%')], order=[('code', 'ASC')]),
- [product1, product2])
- self.assertEqual(Product.search(
- [('name', 'like', '%')], order=[('code', 'DESC')]),
- [product2, product1])
-
- # Inherited field with custom order.
- self.assertEqual(
- Product.search([], order=[('name', 'ASC')]), [product1, product2])
- self.assertEqual(
- Product.search([], order=[('name', 'DESC')]), [product2, product1])
- self.assertEqual(Product.search(
- [('name', 'like', '%')], order=[('name', 'ASC')]),
- [product1, product2])
- self.assertEqual(Product.search(
- [('name', 'like', '%')], order=[('name', 'DESC')]),
- [product2, product1])
-
- # Inherited field without custom order.
- self.assertEqual(
- Product.search([], order=[('type', 'ASC')]), [product1, product2])
- self.assertEqual(
- Product.search([], order=[('type', 'DESC')]), [product2, product1])
- self.assertEqual(Product.search(
- [('name', 'like', '%')], order=[('type', 'ASC')]),
- [product1, product2])
- self.assertEqual(Product.search(
- [('name', 'like', '%')], order=[('type', 'DESC')]),
- [product2, product1])
-
- def test_round_price(self):
- for value, result in [
- (Decimal('1'), Decimal('1.0000')),
- (Decimal('1.12345'), Decimal('1.1234')),
- (1, Decimal('1')),
- ]:
- with self.subTest(value=value):
- self.assertEqual(round_price(value), result)
-
-
-def suite():
- suite = trytond.tests.test_tryton.suite()
- suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
- ProductTestCase))
- suite.addTests(doctest.DocFileSuite(
- 'scenario_product_variant.rst',
- tearDown=doctest_teardown, encoding='utf-8',
- checker=doctest_checker,
- optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
- suite.addTests(doctest.DocFileSuite(
- 'scenario_product_identifier.rst',
- tearDown=doctest_teardown, encoding='utf-8',
- checker=doctest_checker,
- optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
- return suite
diff -r e9312a4a1bf1 -r b777fb7b5121 tests/test_scenario.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test_scenario.py Sat Apr 16 18:30:17 2022 +0200
@@ -0,0 +1,22 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import doctest
+import glob
+import os
+
+from trytond.tests.test_tryton import doctest_checker, doctest_teardown
+
+
+def load_tests(loader, tests, pattern):
+ cwd = os.getcwd()
+ try:
+ os.chdir(os.path.dirname(__file__))
+ for scenario in glob.glob('*.rst'):
+ tests.addTests(doctest.DocFileSuite(
+ scenario, tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ finally:
+ os.chdir(cwd)
+ return tests
diff -r e9312a4a1bf1 -r b777fb7b5121 tox.ini
--- a/tox.ini Mon Apr 11 23:24:21 2022 +0200
+++ b/tox.ini Sat Apr 16 18:30:17 2022 +0200
@@ -2,8 +2,9 @@
envlist = {py37,py38,py39,py310}-{sqlite,postgresql}
[testenv]
+extras = test
commands =
- coverage run --include=.*/product/* setup.py test
+ coverage run --include=.*/product/* -m unittest discover -s tests
coverage report --include=.*/product/* --omit=*/tests/*
deps =
coverage