[Erp5-report] r16780 - in /erp5/trunk/products/ERP5OOo/tests: testOOoStyle.py utils.py
nobody at svn.erp5.org
nobody at svn.erp5.org
Tue Oct 2 17:02:01 CEST 2007
Author: jerome
Date: Tue Oct 2 17:02:01 2007
New Revision: 16780
URL: http://svn.erp5.org?rev=16780&view=rev
Log:
Tests ods_style and odt_style for validity against opendocument schema.
The utility class "Validator" can be reused to validate any OOoTemplate.
Added:
erp5/trunk/products/ERP5OOo/tests/testOOoStyle.py
erp5/trunk/products/ERP5OOo/tests/utils.py
Added: erp5/trunk/products/ERP5OOo/tests/testOOoStyle.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5OOo/tests/testOOoStyle.py?rev=16780&view=auto
==============================================================================
--- erp5/trunk/products/ERP5OOo/tests/testOOoStyle.py (added)
+++ erp5/trunk/products/ERP5OOo/tests/testOOoStyle.py Tue Oct 2 17:02:01 2007
@@ -1,0 +1,149 @@
+##############################################################################
+#
+# Copyright (c) 2007 Nexedi SA and Contributors. All Rights Reserved.
+# Jerome Perrin <jerome at nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import unittest
+from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
+from Testing import ZopeTestCase
+from Products.ERP5OOo.tests.utils import Validator
+
+HTTP_OK = 200
+
+
+class TestOOoStyle(ERP5TypeTestCase, ZopeTestCase.Functional):
+ """Tests ODF styles for ERP5."""
+ skin = None
+ content_type = None
+
+ def getBusinessTemplateList(self):
+ return ('erp5_base', 'erp5_ods_style', 'erp5_odt_style',)
+
+ def afterSetUp(self):
+ if not self.skin:
+ raise NotImplementedError('Subclasses must define skin')
+
+ self.auth = 'ERP5TypeTestCase:'
+ person_module = self.portal.person_module
+ if not hasattr(person_module, 'pers'):
+ person_module.newContent(id='pers', portal_type='Person')
+ self.portal.changeSkin(self.skin)
+ self.validator = Validator()
+
+ def _validate(self, odf_file_data):
+ error_list = self.validator.validate(odf_file_data)
+ if error_list:
+ self.fail(''.join(error_list))
+
+ def test_skin_selection(self):
+ self.assertTrue(self.skin in
+ self.portal.portal_skins.getSkinSelections())
+
+ def test_list_view(self):
+ response = self.publish(
+ '/%s/person_module/PersonModule_viewPersonList'
+ % self.portal.getId(), self.auth)
+ self.assertEquals(HTTP_OK, response.getStatus())
+ content_type = response.getHeader('content-type')
+ self.assertTrue(content_type.startswith(self.content_type), content_type)
+ content_disposition = response.getHeader('content-disposition')
+ self.assertEquals('inline', content_disposition.split(';')[0])
+ self._validate(response.getBody())
+
+ def test_form_view(self):
+ response = self.publish(
+ '/%s/person_module/pers/Person_view'
+ % self.portal.getId(), self.auth)
+ self.assertEquals(HTTP_OK, response.getStatus())
+ content_type = response.getHeader('content-type')
+ self.assertTrue(content_type.startswith(self.content_type), content_type)
+ content_disposition = response.getHeader('content-disposition')
+ self.assertEquals('inline', content_disposition.split(';')[0])
+ self._validate(response.getBody())
+
+ def test_form_view_format(self):
+ # empty format= does not uses oood for conversion
+ response = self.publish(
+ '/%s/person_module/pers/Person_view?format='
+ % self.portal.getId(), self.auth)
+ self.assertEquals(HTTP_OK, response.getStatus())
+ content_type = response.getHeader('content-type')
+ self.assertTrue(content_type.startswith(self.content_type), content_type)
+ content_disposition = response.getHeader('content-disposition')
+ self.assertEquals('inline', content_disposition.split(';')[0])
+ self._validate(response.getBody())
+
+ def test_report_view(self):
+ response = self.publish(
+ '/%s/person_module/pers/Base_viewHistory'
+ % self.portal.getId(), self.auth)
+ self.assertEquals(HTTP_OK, response.getStatus())
+ content_type = response.getHeader('content-type')
+ self.assertTrue(content_type.startswith(self.content_type), content_type)
+ content_disposition = response.getHeader('content-disposition')
+ self.assertEquals('inline', content_disposition.split(';')[0])
+ self._validate(response.getBody())
+
+ def test_report_view_landscape(self):
+ response = self.publish(
+ '/%s/person_module/pers/Base_viewHistory?landscape=1'
+ % self.portal.getId(), self.auth)
+ self.assertEquals(HTTP_OK, response.getStatus())
+ content_type = response.getHeader('content-type')
+ self.assertTrue(content_type.startswith(self.content_type), content_type)
+ content_disposition = response.getHeader('content-disposition')
+ self.assertEquals('inline', content_disposition.split(';')[0])
+ self._validate(response.getBody())
+
+ def test_report_view_sheet_per_report_section(self):
+ response = self.publish(
+ '/%s/person_module/pers/Base_viewHistory?sheet_per_report_section=1'
+ % self.portal.getId(), self.auth)
+ self.assertEquals(HTTP_OK, response.getStatus())
+ content_type = response.getHeader('content-type')
+ self.assertTrue(content_type.startswith(self.content_type), content_type)
+ content_disposition = response.getHeader('content-disposition')
+ self.assertEquals('inline', content_disposition.split(';')[0])
+ self._validate(response.getBody())
+
+
+class TestODTStyle(TestOOoStyle):
+ skin = 'ODT'
+ content_type = 'application/vnd.oasis.opendocument.text'
+
+
+class TestODSStyle(TestOOoStyle):
+ skin = 'ODS'
+ content_type = 'application/vnd.oasis.opendocument.spreadsheet'
+
+
+def test_suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(TestODTStyle))
+ # ODS style is not valid yet
+ # suite.addTest(unittest.makeSuite(TestODSStyle))
+ return suite
+
Added: erp5/trunk/products/ERP5OOo/tests/utils.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5OOo/tests/utils.py?rev=16780&view=auto
==============================================================================
--- erp5/trunk/products/ERP5OOo/tests/utils.py (added)
+++ erp5/trunk/products/ERP5OOo/tests/utils.py Tue Oct 2 17:02:01 2007
@@ -1,0 +1,146 @@
+##############################################################################
+#
+# Copyright (c) 2007 Nexedi SA and Contributors. All Rights Reserved.
+# Jerome Perrin <jerome at nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+"""This module provides utilities for testing ODF files.
+
+Validator: a class defining a `validate` method that expects odf file content
+as first argument and returns list of errors.
+
+"""
+
+import os
+import sys
+import tempfile
+import zipfile
+import popen2
+import urllib2
+from cStringIO import StringIO
+
+try:
+ import libxml2
+except ImportError:
+ libxml2 = None
+try:
+ import odfpy
+except ImportError:
+ odfpy = None
+
+
+if libxml2:
+
+ class ErrorHandler:
+ """Collect errors"""
+ def __init__(self, file_name):
+ libxml2.lineNumbersDefault(1)
+ self.file_name = file_name
+ self.error_list = []
+
+ def onError(self, msg, data):
+ line = libxml2.lastError().line()
+ self.error_list.append('%s:%s: %s' % (self.file_name, line, msg))
+ onWarning = onError
+
+
+ class LibXML2Validator:
+ """Validate ODF document using RelaxNG and libxml2"""
+ schema_url = \
+ 'http://docs.oasis-open.org/office/v1.1/OS/OpenDocument-schema-v1.1.rng'
+
+ def __init__(self, schema_url=schema_url):
+ self.schema_url = schema_url
+ self.schema_path = os.path.join(
+ tempfile.gettempdir(), 'OpenDocument.rng')
+ # download if local copy does not exists
+ if not os.path.exists(self.schema_path):
+ self._download()
+ ctxt = libxml2.relaxNGNewParserCtxt(self.schema_path)
+ self.relaxng = ctxt.relaxNGParse()
+
+ def validate(self, odf_file_content):
+ error_list = []
+ odf_file = StringIO(odf_file_content)
+ for f in ('content.xml', 'meta.xml', 'styles.xml', 'settings.xml'):
+ error_list.extend(self._validateXML(odf_file, f))
+ return error_list
+
+ def _download(self):
+ r = urllib2.urlopen(self.schema_url)
+ out_file = open(self.schema_path, 'w')
+ try:
+ out_file.write(r.read())
+ finally:
+ out_file.close()
+ r.close()
+
+ def _validateXML(self, odf_file, content_file_name):
+ validationCtxt = self.relaxng.relaxNGNewValidCtxt()
+ err = ErrorHandler(content_file_name)
+
+ validationCtxt.setValidityErrorHandler(
+ err.onError, err.onWarning)
+
+ zfd = zipfile.ZipFile(odf_file)
+ content = zfd.read(content_file_name)
+
+ validationCtxt.relaxNGValidateDoc(
+ libxml2.parseMemory(content, len(content)))
+ return err.error_list
+
+ Validator = LibXML2Validator
+
+elif odfpy:
+
+ class OdflintValidator:
+ """Validates ODF files using odflint, available on pypi
+ http://opendocumentfellowship.org/development/projects/odfpy
+ """
+ def validate(self, odf_file_content):
+ fd, file_name = tempfile.mkstemp()
+ os.write(fd, odf_file_content)
+ os.close(fd)
+ stdout, stdin = popen2.popen4('odflint %s' % file_name)
+ stdin.close()
+ error_list = ''
+ for line in stdout:
+ if line.startswith('Error: '):
+ error_list += line
+ os.unlink(file_name)
+ return error_list
+
+ Validator = OdflintValidator
+
+else:
+
+ class NoValidator:
+ """Does not actually validate, but keep the interface."""
+ def validate(self, odf_file_content):
+ print >> sys.stderr, 'No validator available'
+
+ Validator = NoValidator
+
+
More information about the Erp5-report
mailing list