Source code for extools.view.tests.extest_exview

"""ExTests for :py:class:`extools.view.ExView`."""
from unittest import mock
import random

from extools.view import (exview, ExView)
from extools.view.errors import (ExViewError, ExViewOpenError)
from extools.test import ExTestCase

try:
    from accpac import *
except ImportError:
    pass

ORDER_HEADER_VIEWID = "OE0520"
ORDER_DETAIL_VIEWID = "OE0500"
ORDER_OPTFIELD_VIEWID = "OE0522"
DEFAULT_ORDNUMBER = "ORD000000000001"
ORDNUMBER_1 = "ORD000000000001"
ORDNUMBER_2 = "ORD000000000002"

AR_CUSTOMER_VIEWID = "AR0024"
AR_CUSTOMER_COUNT = 27
AR_CUSTOMER_FIRST = "1100"
AR_CUSTOMER_LAST = "WEBCUST"

[docs]def main(*args, **kwargs): """This main hook is picked up by ExTestRunner for automatic execution.""" # ExViewCMTestCase, ExViewExceptionsTestCase, for klass in [ExViewCMTestCase, ExViewInternalsTestCase, ExViewExceptionsTestCase, ExViewViewCacheTestCase, ExViewProxyMethodsTestCase, ]: ext = klass() ext.run()
[docs]class ExViewCMTestCase(ExTestCase): """Test the :py:class:`extools.view.exview` context manager."""
[docs] def test_exview_contextmanager(self): """Verify that the :py:meth:`extools.view.exview` context manager is working: - Opens and seeks to the first record by default. - Opens and seeks to the provided criteria. - Raises on an invalid view id. """ with exview(ORDER_HEADER_VIEWID, self.index) as exv: self.assert_equal(exv.get("ORDNUMBER"), DEFAULT_ORDNUMBER) with exview(ORDER_HEADER_VIEWID, self.index, seek_to={"ORDNUMBER": ORDNUMBER_2}) as exv: self.assert_equal(exv.get("ORDNUMBER"), ORDNUMBER_2) """ TODO: check ViewID is valid before opening. Currently crashes Sage with self.assert_raises(ExViewOpenError): with exview("BADID") as exv: self.exm.info("In exview.") pass """
[docs]class ExViewExceptionsTestCase(ExTestCase): """Verify :py:class:`extools.view.ExView` raises on non-zero returns."""
[docs] def setup_class(self): """Dynamically generate the tests for wrapped methods.""" self.generate_raise_tests()
def _mock_bad_return(self): """Any non-zero return is a failure, try random ones.""" return random.randint(1, 4096)
[docs] def generate_raise_tests(self): """Generate mocked raise tests for all wrapped methods. Dynamically create a test for each method in :py:data:`extools.view.ExView.WRAP`. This should be run during the ``.setup_class()`` hook so that the tests are defined before ``.run()`` is called. """ for method in ExView.WRAP: self._generate_raise_test_for(method) self._generate_no_raise_test_for(method)
def _generate_no_raise_test_for(self, method): def test_doesnt_raise(): """Verify that wrapped methods do not raise on 0 returns. This test is to make sure that the wrapping of this function is working properly. The ``accpac.View`` is mocked out and always returns a zero. """ with mock.patch("accpac.View") as MockView: instance = MockView.return_value _method = getattr(instance, method) _method.return_value = 0 exv = ExView(ORDER_HEADER_VIEWID, self.index) exv._view = MockView() getattr(exv, method)() setattr(self, "test_{}_doesnt_raise".format(method), test_doesnt_raise) def _generate_raise_test_for(self, method): def test_raises(): """Verify that wrapped methods raise on non-zero returns. This test is to make sure that the wrapping of this function is working properly. The ``accpac.View`` is mocked out and always returns a non-zero value. """ with mock.patch("accpac.View") as MockView: instance = MockView.return_value _method = getattr(instance, method) _method.return_value = self._mock_bad_return() exv = ExView(ORDER_HEADER_VIEWID, self.index) exv._view = MockView() with self.assert_raises(ExViewError): getattr(exv, method)() setattr(self, "test_{}_raises".format(method), test_raises)
[docs]class ExViewInternalsTestCase(ExTestCase): """Verify :py:class:`extools.view.ExView` internals are working."""
[docs] def setup(self): """Clear the class internals before each test.""" ExView._view_cache = {}
[docs] def test_index_detection(self): """Verify indexes are identified through introspection on init.""" indexes = [['ORDUNIQ', ], ['ORDNUMBER', ], ['CUSTOMER', ], ['TYPE', 'COMPLETE', 'ORDUNIQ', ], ['CUSTOMER', 'ORDNUMBER', ], ['REFERENCE', 'ORDNUMBER', ], ['CUSTOMER', 'PONUMBER', ], ['CUSTOMER', 'ONHOLD', 'TYPE', ], ['COMPANYID', 'OPPOID', ], ] with exview(ORDER_HEADER_VIEWID, self.index) as exv: # Check that we have the right number of indexes self.assert_equal(len(exv.indexes), len(indexes)) # And then that they're the right one. for index in indexes: self.assert_true(index in exv.indexes)
[docs] def test_detail_view_detection(self): """Verify that detail views are detected and helpers added.""" detail_attribs = ['lines', 'lines_from', 'lines_where', ] # Make sure the header is not identified as a detail view with exview(ORDER_HEADER_VIEWID, self.index) as exv: self.assert_true(not exv.detail_view) # The detail view should be set after the compose completes exv.compose() self.assert_true(exv.detail_view) # And it shouldn't point to self. self.assert_true(exv.detail_view != exv) # For each of the dynamic methods, check that the're defined for attrib in detail_attribs: self.assert_true(hasattr(exv, attrib)) self.assert_true(hasattr(exv.detail_view, attrib)) # But the Order Detail view is identified as one with exview(ORDER_DETAIL_VIEWID, self.index) as exv: self.assert_true(exv.detail_view) self.assert_true(exv.detail_view == exv) return True
[docs] def test_intial_optfield_view_detection(self): """Verify that optfield views are detected and helpers added.""" # Make sure the header is not identified as an optional field view with exview(ORDER_HEADER_VIEWID, self.index) as exv: self.assert_true(not exv.optfield_view) # But the Order optional field view is identified as one with exview(ORDER_OPTFIELD_VIEWID, self.index) as exv: self.assert_true(exv.optfield_view) self.assert_true(exv.optfield_view == exv)
[docs] def test_compose_optfield_view_detection(self): """Verify that optfield views are detected and helpers added.""" optfield_attribs = ['create_optfield', 'has_optfield', 'all_optfields', 'update_optfield', 'update_or_create_optfield', 'delete_optfield', ] # Check that on compose, the optfield_view and helpers are correct. with exview(ORDER_HEADER_VIEWID, self.index) as exv: # The optfield view should be set after the compose completes exv.compose() self.assert_true(exv.optfield_view) # And it shouldn't point to self. self.assert_true(exv.optfield_view != exv) # For each of the dynamic methods, check that the're defined for attrib in optfield_attribs: self.assert_true(hasattr(exv, attrib)) self.assert_true(hasattr(exv.optfield_view, attrib)) return True
[docs] def test_composed_view_list(self): """Verify that the list of composed views is determined correctly.""" view_list = ['OE0500', None, 'OE0180', 'OE0740', 'OE0526', 'OE0522', ] with exview(ORDER_HEADER_VIEWID, self.index) as exv: # Check that we have the right number of views. self.assert_equal(len(exv._views), len(view_list)) # And then that they're the right ones. for view in [v if v else None for v in view_list]: self.assert_true(view in exv._views)
[docs] def test_field_names(self): """Verify that the list of fiel names is determined correctly.""" order_header_field_count = 406 order_header_first_field = "ORDUNIQ" order_header_last_field = "PMTTYPEID" with exview(ORDER_HEADER_VIEWID, self.index) as exv: # field names shoud be populated on introspection self.assert_equal(len(exv.field_names), order_header_field_count) self.assert_equal(exv.field_names[0], order_header_first_field) self.assert_equal(exv.field_names[-1], order_header_last_field)
[docs] def test_view_cache(self): """Verify that the view cache is populated correctly.""" compose_tree = ["OE0520", "OE0500", "OE0740", "OE0180", "OE0526", "OE0522", "OE0508", "OE0507", "OE0501", "OE0502", "OE0504", "OE0506", "OE0503", ] with exview(ORDER_HEADER_VIEWID, self.index) as exv: # After starting up self should be in the cache. self.assert_equal(list(exv._view_cache.keys()), [ORDER_HEADER_VIEWID, ]) # On compose, the full tree should be in cache. exv.compose() self.assert_equal(len(exv._view_cache.keys()), len(compose_tree)) for (viewid, view) in exv._view_cache.items(): # It is one of the ones we expect... self.assert_true(viewid in compose_tree) # And is actually a view with the correct view id self.assert_true(isinstance(view, ExView)) self.assert_equal(view.rotoid, viewid) return True
[docs] def test_detail_view_wrapper(self): """Verify that the detail view wrappers work as expected.""" detail_lines = 4 items = ["A1-103/0", "A1-105/0" ,"A1-400/0" , "A1-450/0", ] with exview(ORDER_HEADER_VIEWID, self.index, seek_to={'ORDNUMBER': DEFAULT_ORDNUMBER}) as exv: exv.compose() self.assert_equal([l.get("ITEM") for l in exv.lines()], items) exv.oe0500.seek_to() self.assert_equal([l.get("ITEM") for l in exv.lines_from(1,2)], items[1:3]) exv.oe0500.seek_to() self.assert_equal([l.get("ITEM") for l in exv.lines_where( ITEM=items[-1]) ], items[-1:])
[docs] def test_optfield_view_wrapper(self): """Verify that the optfield view wrappers work as expected.""" optional_field = "CREDTWARNING" optional_field_value = "0" optional_field_update_value = "1" optional_field_count = 13 bad_optional_field = "IDONTEXIST" # Open the order headers view. with exview(ORDER_HEADER_VIEWID, index=self.index, seek_to={'ORDNUMBER': DEFAULT_ORDNUMBER}) as exv: exv.compose() # Get all optional fields, check count and presence optfields = [o.get("OPTFIELD") for o in exv.all_optfields()] self.assert_equal(len(optfields), optional_field_count) self.assert_true(optional_field in optfields) self.exm.debug("has {}? {}".format( optional_field, exv.has_optfield(optional_field))) # Does it have optional field? Yes self.assert_true(exv.has_optfield(optional_field)) self.assert_equal(exv.get_optfield(optional_field).strip(), optional_field_value) # Does it have bad optional field? No - Crashes Sage """ TODO: filter optfields before call. self.assert_true(not exv.has_optfield(bad_optional_field)) """ self.exm.debug("Deleting {}".format(optional_field)) # Delete good optional field exv.delete_optfield(optional_field) # Delete bad optional field - raises # Create bad optional field with value "CREATE" - raises """ TODO: filter optfields before call. with self.assert_raises(ExViewError): exv.delete_optfield(optional_field) with self.assert_raises(ExViewError): exv.create_optfield(bad_optional_field, "CREATE") """ # Create optional field with value "No" exv.create_optfield(optional_field, optional_field_value) self.assert_equal(exv.get_optfield(optional_field).strip(), optional_field_value) # Update optional field with value "Yes" exv.update_optfield(optional_field, optional_field_update_value) self.assert_equal(exv.get_optfield(optional_field).strip(), optional_field_update_value) # Delete optional field exv.delete_optfield(optional_field) self.assert_true(not exv.has_optfield(optional_field)) # Create or update optional field with value "Yes" exv.update_or_create_optfield(optional_field, optional_field_update_value) self.assert_equal(exv.get_optfield(optional_field).strip(), optional_field_update_value) # Create or update optional field with value "No" exv.update_or_create_optfield(optional_field, optional_field_value) self.assert_equal(exv.get_optfield(optional_field).strip(), optional_field_value)
[docs]class ExViewViewCacheTestCase(ExTestCase): """Verify :py:class:`extools.view.ExView` view cache is working."""
[docs] def setup(self): """Clear the class internals before each test.""" ExView._view_cache = {}
[docs] def test__view_cache(self): """Verify that _view_cache returns the cache namespace.""" with exview(ORDER_HEADER_VIEWID, self.index) as exv: v, c = exv.cached_view(ORDER_HEADER_VIEWID) self.assert_true(not c) self.assert_true(v) ns = exv._view_cache self.assert_true(len(ns) == 1) self.assert_true(ORDER_HEADER_VIEWID in ns.keys())
[docs] def test_cached_view(self): """Verify that cached_view returns views in the cache namespace.""" with exview(ORDER_HEADER_VIEWID, self.index) as exv: v, c = exv.cached_view(ORDER_HEADER_VIEWID) self.assert_true(not c) self.assert_true(v)
[docs] def test_cached_view_create(self): """Verify that cached_view returns view in the cache namespace.""" with exview(ORDER_HEADER_VIEWID, self.index) as exv: v, c = exv.cached_view(ORDER_DETAIL_VIEWID) self.assert_true(c) self.assert_true(v)
[docs] def test_remove_cached_view(self): """Verify that remove_cached_view removes from the cache namespace.""" with exview(ORDER_HEADER_VIEWID, self.index) as exv: v, c = exv.cached_view(ORDER_DETAIL_VIEWID) self.assert_true(c) self.assert_true(v) exv.remove_cached_view(ORDER_DETAIL_VIEWID) self.assert_true(ORDER_DETAIL_VIEWID not in exv._view_cache.keys())
[docs]class ExViewProxyMethodsTestCase(ExTestCase): """Verify :py:class:`extools.view.ExView` proxy methods are working."""
[docs] def setup(self): """Clear the class internals before each test.""" ExView._view_cache = {}
[docs] def test_all(self): """Verify that ``all`` yields all records in a view.""" with exview(AR_CUSTOMER_VIEWID, self.index) as exv: customers = [c.get("IDCUST") for c in exv.all()] self.assert_equal(len(customers), AR_CUSTOMER_COUNT) self.assert_equal(customers[0], AR_CUSTOMER_FIRST) self.assert_equal(customers[-1], AR_CUSTOMER_LAST)
[docs] def test_where(self): """Verify that ``where`` yields all matching in a view.""" barmart_customers = ["1100", "1105", "BARMART", ] with exview(AR_CUSTOMER_VIEWID, self.index) as exv: customers = [c.get("IDCUST") for c in exv.where(IDNATACCT='BARMART')] self.assert_equal(len(customers), len(barmart_customers)) for i in range(0, len(customers)): self.assert_equal(customers[i], barmart_customers[i])
[docs] def test_create(self): """Verify that ``where`` yields all matching in a view.""" with exview(ORDER_HEADER_VIEWID, self.index) as exv: exv.compose() lines = len([l for l in exv.lines()]) exv.oe0500.create(ITEM="A1-103/0") self.assert_equal(lines + 1, len([l for l in exv.lines()])) self.exm.info([l.get("ITEM") for l in exv.lines()])
def test_update(self): pass def test_fetch(self): pass def test_order(self): pass def test_close(self): pass def test_seek_to(self): pass
[docs]class ExViewAttributesTestCase(ExTestCase): """Verify :py:class:`extools.view.ExView` passes attrs to the view.""" attrs = ['handle', ]
[docs] def setup_class(self): """Generate the attribute proxy tests.""" pass
[docs] def setup(self): """Clear the class internals before each test.""" ExView._view_cache = {}
def generate_attr_tests(self): pass