Anonymous avatar Anonymous committed d6624bc

0.12dev: merged [8189:8193/sandbox/rework-testing], alternate db backend for unit-tests and Makefile improvements.

Comments (0)

Files changed (22)

+# Makefile for testing Trac (see doc/dev/testing.rst)
+# ----------------------------------------------------------------------------
+
+# copy Makefile.cfg.sample to Makefile.cfg and adapt to your local environment.
+-include Makefile.cfg
+
+# ----------------------------------------------------------------------------
+ifeq "$(OS)" "Windows_NT"
+    SEP = ;
+else
+    SEP = :
+endif
+
+export TRAC_TEST_DB_URI = $($(db).uri)
+export PATH := $(python.$(if $(python),$(python),$($(db).python)))$(SEP)$(PATH)
+export PYTHONPATH := .$(SEP)$(PYTHONPATH)
+# ----------------------------------------------------------------------------
+
+
 .PHONY: all
+ifdef test
+all: status
+	python $(test)
+else
 all:
+	@echo "make test|unit-test|functional-test|test=... [db=...] [python=...]"
+endif
+
+.PHONY: status
+status:
+	@python -V
+	@echo PYTHONPATH=$$PYTHONPATH
 
 .PHONY: clean
 clean:
 test: unit-test functional-test
 
 unit-test: Trac.egg-info
-	PYTHONPATH=$(pythonpath) python ./trac/test.py --skip-functional-tests
+	python ./trac/test.py --skip-functional-tests
 
 functional-test: Trac.egg-info
-	PYTHONPATH=$(pythonpath) python trac/tests/functional/__init__.py -v
+	python trac/tests/functional/__init__.py -v
 
 .PHONY: coverage
 coverage: html/index.html
 	figleaf2html --exclude-patterns=trac/tests/figleaf-exclude .figleaf.functional .figleaf.unittests
 
 .figleaf.functional: Trac.egg-info
-	PYTHONPATH=$(pythonpath) FIGLEAF=figleaf python trac/tests/functional/__init__.py -v
+	FIGLEAF=figleaf python trac/tests/functional/__init__.py -v
 	mv .figleaf .figleaf.functional
 
 .figleaf.unittests: Trac.egg-info
 	rm -f .figleaf .figleaf.unittests
-	PYTHONPATH=$(pythonpath) figleaf ./trac/test.py --skip-functional-tests
+	figleaf ./trac/test.py --skip-functional-tests
 	mv .figleaf .figleaf.unittests
 
-Trac.egg-info:
+Trac.egg-info: status
 	python setup.py egg_info
 
-
-# Platform dependent
-ifeq "$(OS)" "Windows_NT"
-    pythonpath = "$$PYTHONPATH;$$PWD"
-else
-    pythonpath = $$PYTHONPATH:$$PWD
-endif

Makefile.cfg.sample

+# Makefile configuration file sample 
+#
+# Adapt to your local setting and copy to Makefile.cfg
+#
+# ----------------------------------------------------------------------------
+# Python Installations (select with `python=` on the `make` command line)
+
+python.23 =
+python.24 =
+python.25 = C:/Dev/Python254
+python.ap25 = C:/Dev/ActivePython254
+python.26 = C:/Dev/Python261
+python.27 =
+
+# default Python version (if not defined, pick the one from the path)
+.python =
+
+# ----------------------------------------------------------------------------
+# Database Backends (select with `db=` on the `make` command line)
+
+# db URIs 
+mysql.uri = mysql://tracuser:tracpassword@localhost/trac
+postgres.uri = postgres://tracuser:tracpassword@localhost:5432/trac?schema=tractest
+
+# default db backend (if not defined, use in-memory sqlite)
+.uri =
+
+# default Python versions to use when `db` is specified
+mysql.python = 25
+postgres.python = 26

doc/dev/testing.rst

 This will run the unit tests first, then the functional tests (if you have the
 dependencies) against sqlite.  On a reasonably fast machine, the former takes
 10 seconds and the latter a couple of minutes.  If you're running them on
-Windows, you'll need to manually run the tests using :command:`python
-trac\\test.py`, but this will run all the tests interleaved.  Examine the
-:file:`Makefile` if you want more control.
+Windows and don't have cygwin, you'll need to manually run the tests using 
+:command:`python trac\\test.py`, but this will run all the tests interleaved.
+Examine the :file:`Makefile` if you want more control.
+Other possible usages::
+  
+  make test=trac/tests/allwiki.py # run all the Wiki formatter tests
+  
+  make unit-test db=postgres # run only the unit tests with PostgreSQL
 
+  make functional-test db=mysql # run only the functional tests with MySQL
+
+  make test python=24 # run all the tests using Python 2.4
 
 
 
 from trac.config import Configuration
 from trac.core import Component, ComponentManager, ExtensionPoint
 from trac.env import Environment
+from trac.db.api import _parse_db_str, DatabaseManager
 from trac.db.sqlite_backend import SQLiteConnection
+import trac.db.postgres_backend
+import trac.db.mysql_backend
 from trac.ticket.default_workflow import load_workflow_config_snippet
 from trac.util import translation
 
         self.fixture = fixture
 
 
+# -- Database utilities
+
+def get_dburi():
+    if os.environ.has_key('TRAC_TEST_DB_URI'):
+        dburi = os.environ['TRAC_TEST_DB_URI']
+        if dburi:
+            scheme, db_prop = _parse_db_str(dburi)
+            # Assume the schema 'tractest' for Postgres
+            if scheme == 'postgres' and \
+                    not db_prop.get('params', {}).get('schema'):
+                if '?' in dburi:
+                    dburi += "&schema=tractest"
+                else:
+                    dburi += "?schema=tractest"
+            return dburi
+    return 'sqlite:db/trac.db'
+
+
+def reset_postgres_db(db, db_prop):
+    dbname = db.schema
+    if dbname:
+        cursor = db.cursor()
+        # reset sequences
+        cursor.execute('SELECT sequence_name '
+                       'FROM information_schema.sequences '
+                       'WHERE sequence_schema=%s', (dbname,))
+        for seq in cursor.fetchall():
+            cursor.execute('ALTER SEQUENCE %s RESTART WITH 1' % seq)
+        # clear tables
+        cursor.execute('SELECT table_name FROM information_schema.tables '
+                       'WHERE table_schema=%s', (dbname,))
+        tables = cursor.fetchall()
+        for table in tables:
+            # PostgreSQL supports TRUNCATE TABLE as well 
+            # (see http://www.postgresql.org/docs/8.1/static/sql-truncate.html)
+            # but on the small tables used here, DELETE is actually much faster
+            cursor.execute('DELETE FROM %s' % table)
+        db.commit()
+        return tables
+
+def reset_mysql_db(db, db_prop):
+    dbname = os.path.basename(db_prop['path'])
+    if dbname:
+        cursor = db.cursor()
+        cursor.execute('SELECT table_name FROM information_schema.tables '
+                       'WHERE table_schema=%s', (dbname,))
+        tables = cursor.fetchall()
+        for table in tables:
+            # TRUNCATE TABLE is prefered to DELETE FROM, as we need to reset
+            # the auto_increment in MySQL.
+            cursor.execute('TRUNCATE TABLE %s' % table)
+        db.commit()
+        return tables
+
+
 class InMemoryDatabase(SQLiteConnection):
     """
     DB-API connection object for an SQLite in-memory database, containing all
         self.cnx.commit()
 
 
+# -- Environment stub
+
 class EnvironmentStub(Environment):
     """A stub of the trac.env.Environment object for testing."""
 
     href = abs_href = None
+    dbenv = db = None
 
     def __init__(self, default_data=False, enable=None):
         """Construct a new Environment stub object.
         ComponentManager.__init__(self)
         Component.__init__(self)
         self.enabled_components = enable or ['trac.*']
-        self.db = InMemoryDatabase()
         self.systeminfo = [('Python', sys.version)]
 
         import trac
         if not os.path.isabs(self.path):
             self.path = os.path.join(os.getcwd(), self.path)
 
+        # -- configuration
         self.config = Configuration(None)
         # We have to have a ticket-workflow config for ''lots'' of things to
         # work.  So insert the basic-workflow config here.  There may be a
         # better solution than this.
         load_workflow_config_snippet(self.config, 'basic-workflow.ini')
+        self.config.set('logging', 'log_level', 'DEBUG')
+        self.config.set('logging', 'log_type', 'stderr')
 
+        # -- logging
         from trac.log import logger_factory
         self.log = logger_factory('test')
 
+        # -- database
+        self.dburi = get_dburi()
+        if self.dburi.startswith('sqlite'):
+            self.db = InMemoryDatabase()
+
+        if default_data:
+            self.reset_db(default_data)
+
         from trac.web.href import Href
         self.href = Href('/trac.cgi')
         self.abs_href = Href('http://example.org/trac.cgi')
 
-        from trac import db_default
-        if default_data:
-            cursor = self.db.cursor()
-            for table, cols, vals in db_default.get_data(self.db):
-                cursor.executemany("INSERT INTO %s (%s) VALUES (%s)"
-                                   % (table, ','.join(cols),
-                                      ','.join(['%s' for c in cols])),
-                                   vals)
-            self.db.commit()
-            
         self.known_users = []
         translation.activate(Locale and Locale('en', 'US'))
 
         return False
 
     def get_db_cnx(self):
-        return self.db
+        if self.db:
+            return self.db # in-memory SQLite
+
+        # As most of the EnvironmentStubs are built at startup during
+        # the test suite formation and the creation of test cases, we can't
+        # afford to create a real db connection for each instance.
+        # So we create a special EnvironmentStub instance in charge of
+        # getting the db connections for all the other instances.
+        dbenv = EnvironmentStub.dbenv
+        if not dbenv:
+            dbenv = EnvironmentStub.dbenv = EnvironmentStub()
+            dbenv.config.set('trac', 'database', self.dburi)
+            self.reset_db() # make sure we get rid of garbage from previous run
+        return DatabaseManager(dbenv).get_connection()
+
+    def reset_db(self, default_data=None):
+        """Remove all data from Trac tables, keeping the tables themselves.
+        :param default_data: after clean-up, initialize with default data
+        :return: True upon success
+        """
+        if EnvironmentStub.dbenv:
+            db = self.get_db_cnx()
+            scheme, db_prop = _parse_db_str(self.dburi)
+
+            tables = []
+            db.rollback() # make sure there's no transaction in progress
+            try:
+                m = sys.modules[__name__]
+                reset_fn = 'reset_%s_db' % scheme
+                if hasattr(m, reset_fn):
+                    tables = getattr(m, reset_fn)(db, db_prop)
+            except:
+                db.rollback() # tables are likely missing
+
+            if not tables:
+                del db
+                DatabaseManager(EnvironmentStub.dbenv).init_db()
+
+        from trac import db_default
+        if default_data:
+            db = self.get_db_cnx()
+            cursor = db.cursor()
+            for table, cols, vals in db_default.get_data(db):
+                cursor.executemany("INSERT INTO %s (%s) VALUES (%s)"
+                                   % (table, ','.join(cols),
+                                      ','.join(['%s' for c in cols])),
+                                   vals)
+            db.commit()
 
     def get_known_users(self, cnx=None):
         return self.known_users

trac/tests/attachment.py

 
     def tearDown(self):
         shutil.rmtree(self.env.path)
+        self.env.reset_db()
 
     def test_get_path(self):
         attachment = Attachment(self.env, 'ticket', 42)

trac/tests/functional/testenv.py

 #!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
 """Object for creating and destroying a Trac environment for testing purposes.
 Provides some Trac environment-wide utility functions, and a way to call
 :command:`trac-admin` without it being on the path."""
 import sys
 import errno
 import locale
+from subprocess import call, Popen, PIPE, STDOUT
 
-from subprocess import call, Popen, PIPE, STDOUT
+from trac.db.api import _parse_db_str
+from trac.env import open_environment
+from trac.test import EnvironmentStub, get_dburi
 from trac.tests.functional.compat import rmtree, close_fds
 from trac.tests.functional import logfile
 from trac.tests.functional.better_twill import tc, ConnectError
-from trac.env import open_environment
-from trac.db.api import _parse_db_str, DatabaseManager
 from trac.db.mysql_backend import MySQLConnection
 from trac.db.postgres_backend import PostgreSQLConnection
 from trac.util.compat import close_fds
         self.create()
         locale.setlocale(locale.LC_ALL, '')
 
-    def get_dburi(self):
-        if os.environ.has_key('TRAC_TEST_DB_URI'):
-            dburi = os.environ['TRAC_TEST_DB_URI']
+    dburi = property(lambda x: get_dburi())
 
-            scheme, db_prop = _parse_db_str(dburi)
-            # Assume the schema 'tractest' for Postgres
-            if scheme == 'postgres' and db_prop.get('schema'):
-                if '?' in dburi:
-                    dburi += "&schema=tractest"
-                else:
-                    dburi += "?schema=tractest"
-            return dburi
-        return 'sqlite:db/trac.db'
-    dburi = property(get_dburi)
+    def destroy_db(self, db):
+        scheme, db_prop = _parse_db_str(self.dburi)
 
-    def destroy_mysqldb(self, db, db_prop):
-        dbname = os.path.basename(db_prop['path'])
+        cursor = db.cursor()
         try:
-            cursor = db.cursor()
-            cursor.execute('SELECT table_name FROM information_schema.tables '
-                           'WHERE table_schema=%s', (dbname,))
-            tables = cursor.fetchall()
-            for t in tables:
-                cursor.execute('DROP TABLE IF EXISTS `%s`' % t)
+            if scheme == 'postgres' and db.schema:
+                cursor.execute('DROP SCHEMA "%s" CASCADE' % db.schema)
+            elif scheme == 'mysql':
+                dbname = os.path.basename(db_prop['path'])
+                cursor = db.cursor()
+                cursor.execute('SELECT table_name FROM information_schema.tables '
+                               'WHERE table_schema=%s', (dbname,))
+                tables = cursor.fetchall()
+                for t in tables:
+                    cursor.execute('DROP TABLE IF EXISTS `%s`' % t)
             db.commit()
         except Exception, e:
-            print e
             db.rollback()
 
-    def destroy_postgresql(self, db):
-        # We'll remove the schema automatically for Postgres, if it
-        # exists.
-        # With this, you can run functional tests multiple times without
-        # running external tools (just like when running against sqlite)
-        if db.schema:
-            try:
-                cursor = db.cursor()
-                cursor.execute('DROP SCHEMA "%s" CASCADE' % db.schema)
-                db.commit()
-            except: 
-                # if drop schema fails, either it's already gone
-                # or a manual drop will be needed
-                db.rollback()
-
     def destroy(self):
         """Remove all of the test environment data."""
-        scheme, db_prop = _parse_db_str(self.dburi)
-        if scheme == 'postgres':
-            db = PostgreSQLConnection(**db_prop)
-            self.destroy_postgresql(db)
-        elif scheme == 'mysql':
-            db = MySQLConnection(**db_prop)
-            self.destroy_mysqldb(db, db_prop)
+        env = EnvironmentStub()
+        self.destroy_db(env.get_db_cnx())
+        env.shutdown()
 
         self.destroy_repo()
         if os.path.exists(self.dirname):
                      close_fds=close_fds, cwd=self.work_dir())
         (data, _) = proc.communicate()
         if proc.wait():
-            raise Exception('Unable to run command %s in %s' % (args, self.work_dir()))
+            raise Exception('Unable to run command %s in %s' %
+                            (args, self.work_dir()))
 
         logfile.write(data)
         return data

trac/tests/perm.py

                                            perm.DefaultPermissionGroupProvider])
         self.store = perm.DefaultPermissionStore(self.env)
 
+    def tearDown(self):
+        self.env.reset_db()
+
     def test_simple_actions(self):
         db = self.env.get_db_cnx()
         cursor = db.cursor()
                                            TestPermissionRequestor])
         self.perm = perm.PermissionSystem(self.env)
 
+    def tearDown(self):
+        self.env.reset_db()
+
     def test_all_permissions(self):
         self.assertEqual({'EMAIL_VIEW': True, 'TRAC_ADMIN': True,
                           'TEST_CREATE': True, 'TEST_DELETE': True,
         self.perm_system.grant_permission('testuser', 'TEST_ADMIN')
         self.perm = perm.PermissionCache(self.env, 'testuser')
 
+    def tearDown(self):
+        self.env.reset_db()
+
     def test_contains(self):
         self.assertEqual(True, 'TEST_MODIFY' in self.perm)
         self.assertEqual(True, 'TEST_ADMIN' in self.perm)
         self.policy = TestPermissionPolicy(self.env)
         self.perm = perm.PermissionCache(self.env, 'testuser')
 
+    def tearDown(self):
+        self.env.reset_db()
+
     def test_no_permissions(self):
         self.assertRaises(perm.PermissionError,
                           self.perm.assert_permission, 'TEST_MODIFY')

trac/tests/wikisyntax.py

 
 def attachment_teardown(tc):
     shutil.rmtree(tc.env.path)
+    tc.env.reset_db()
 
 def suite():
     suite = unittest.TestSuite()

trac/ticket/tests/api.py

         self.ticket_system = TicketSystem(self.env)
         self.req = Mock()
 
+    def tearDown(self):
+        self.env.reset_db()
+
     def _ts_get_available_actions(self, ts, ticket_dict):
         ticket = Ticket(self.env)
         ticket.populate(ticket_dict)

trac/ticket/tests/conversion.py

                         environ={}, perm=[], authname='-', args={}, tz=None,
                         locale='', session=None, form_token=None)
 
+    def tearDown(self):
+        self.env.reset_db()
+
     def _create_a_ticket(self):
         # 1. Creating ticket
         ticket = Ticket(self.env)

trac/ticket/tests/model.py

         self.env.config.set('ticket-custom', 'cbon', 'checkbox')
         self.env.config.set('ticket-custom', 'cboff', 'checkbox')
 
+    def tearDown(self):
+        self.env.reset_db()
+
     def _insert_ticket(self, summary, **kw):
         """Helper for inserting a ticket into the database"""
         ticket = Ticket(self.env)
     def setUp(self):
         self.env = EnvironmentStub(default_data=True)
 
+    def tearDown(self):
+        self.env.reset_db()
+
     def test_priority_fetch(self):
         prio = Priority(self.env, 'major')
         self.assertEqual(prio.name, 'major')
         self.env = EnvironmentStub(default_data=True)
         self.db = self.env.get_db_cnx()
 
+    def tearDown(self):
+        self.env.reset_db()
+
     def test_new_milestone(self):
         milestone = Milestone(self.env)
         self.assertEqual(False, milestone.exists)
 
 
 class ComponentTestCase(unittest.TestCase):
+
     def setUp(self):
         self.env = EnvironmentStub(default_data=True)
 
+    def tearDown(self):
+        self.env.reset_db()
+
     def test_exists_negative(self):
         def get_fake_component():
             return Component(self.env, "Shrubbery")
     def setUp(self):
         self.env = EnvironmentStub(default_data=True)
 
+    def tearDown(self):
+        self.env.reset_db()
+
     def test_exists_negative(self):
         def get_fake_version():
             return Version(self.env, "-1")

trac/ticket/tests/notification.py

     def tearDown(self):
         """Signal the notification test suite that a test is over"""
         notifysuite.tear_down()
+        self.env.reset_db()
 
     def test_recipients(self):
         """To/Cc recipients"""

trac/ticket/tests/query.py

 import unittest
 import difflib
 
-if sqlite_version < 30203:
-    def exp(var):
-        return "1*%s" % var
-else:
-    def exp(var):
-        return "CAST(%s AS int)" % var
+# Note: we don't want to replicate 1:1 all the SQL dialect abstraction
+#       methods from the trac.db layer here. 
 
 class QueryTestCase(unittest.TestCase):
 
         self.env = EnvironmentStub(default_data=True)
         self.req = Mock(href=self.env.href, authname='anonymous', tz=utc)
         
+    def tearDown(self):
+        self.env.reset_db()
 
     def test_all_ordered_by_id(self):
         query = Query(self.env, order='id')
 """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.milestone AS milestone,t.time AS time,t.changetime AS changetime,priority.value AS priority_value
 FROM ticket AS t
   LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
-ORDER BY COALESCE(priority.value,'')='',""" + exp("priority.value") + """,t.id""")
+ORDER BY COALESCE(priority.value,'')='',%(cast_priority)s,t.id""" % {
+          'cast_priority': self.env.get_db_cnx().cast('priority.value', 'int')})
         self.assertEqual([], args)
         tickets = query.execute(self.req)
 
 """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.milestone AS milestone,t.time AS time,t.changetime AS changetime,priority.value AS priority_value
 FROM ticket AS t
   LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
-ORDER BY COALESCE(priority.value,'')='' DESC,""" + exp("priority.value") + """ DESC,t.id""")
+ORDER BY COALESCE(priority.value,'')='' DESC,%(cast_priority)s DESC,t.id""" % {
+          'cast_priority': self.env.get_db_cnx().cast('priority.value', 'int')})
         self.assertEqual([], args)
         tickets = query.execute(self.req)
 
 """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.milestone AS milestone,t.component AS component,t.priority AS priority,t.time AS time,t.changetime AS changetime,priority.value AS priority_value
 FROM ticket AS t
   LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
-ORDER BY COALESCE(priority.value,'')='',""" + exp("priority.value") + """,t.id""")
+ORDER BY COALESCE(priority.value,'')='',%(cast_priority)s,t.id""" % {
+          'cast_priority': self.env.get_db_cnx().cast('priority.value', 'int')})
         self.assertEqual([], args)
         tickets = query.execute(self.req)
 
 """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.milestone AS milestone,t.time AS time,t.changetime AS changetime,priority.value AS priority_value
 FROM ticket AS t
   LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
-WHERE COALESCE(t.owner,'') LIKE %s ESCAPE '/'
-ORDER BY COALESCE(t.id,0)=0,t.id""")
+WHERE COALESCE(t.owner,'') %(like)s
+ORDER BY COALESCE(t.id,0)=0,t.id""" %  {'like': self.env.get_db_cnx().like()})
         self.assertEqual(['%someone%'], args)
         tickets = query.execute(self.req)
 
 """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.milestone AS milestone,t.time AS time,t.changetime AS changetime,priority.value AS priority_value
 FROM ticket AS t
   LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
-WHERE COALESCE(t.owner,'') NOT LIKE %s ESCAPE '/'
-ORDER BY COALESCE(t.id,0)=0,t.id""")
+WHERE COALESCE(t.owner,'') NOT %(like)s
+ORDER BY COALESCE(t.id,0)=0,t.id""" %  {'like': self.env.get_db_cnx().like()})
         self.assertEqual(['%someone%'], args)
         tickets = query.execute(self.req)
 
 """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.milestone AS milestone,t.time AS time,t.changetime AS changetime,priority.value AS priority_value
 FROM ticket AS t
   LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
-WHERE COALESCE(t.owner,'') LIKE %s ESCAPE '/'
-ORDER BY COALESCE(t.id,0)=0,t.id""")
+WHERE COALESCE(t.owner,'') %(like)s
+ORDER BY COALESCE(t.id,0)=0,t.id""" %  {'like': self.env.get_db_cnx().like()})
         self.assertEqual(['someone%'], args)
         tickets = query.execute(self.req)
 
 """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.milestone AS milestone,t.time AS time,t.changetime AS changetime,priority.value AS priority_value
 FROM ticket AS t
   LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
-WHERE COALESCE(t.owner,'') LIKE %s ESCAPE '/'
-ORDER BY COALESCE(t.id,0)=0,t.id""")
+WHERE COALESCE(t.owner,'') %(like)s
+ORDER BY COALESCE(t.id,0)=0,t.id""" %  {'like': self.env.get_db_cnx().like()})
         self.assertEqual(['%someone'], args)
         tickets = query.execute(self.req)
 
 """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.milestone AS milestone,t.time AS time,t.changetime AS changetime,priority.value AS priority_value
 FROM ticket AS t
   LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
-WHERE (COALESCE(t.owner,'') LIKE %s ESCAPE '/' OR COALESCE(t.owner,'') LIKE %s ESCAPE '/')
-ORDER BY COALESCE(t.id,0)=0,t.id""")
+WHERE (COALESCE(t.owner,'') %(like)s OR COALESCE(t.owner,'') %(like)s)
+ORDER BY COALESCE(t.id,0)=0,t.id""" % {'like': self.env.get_db_cnx().like()})
         tickets = query.execute(self.req)
 
     def test_constrained_by_empty_value_contains(self):
 """SELECT t.id AS id,t.summary AS summary,t.time AS time,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.changetime AS changetime,priority.value AS priority_value
 FROM ticket AS t
   LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
-WHERE (""" + exp("t.time") + ">=%s AND " + exp("t.time") + """<%s)
-ORDER BY COALESCE(t.id,0)=0,t.id""")
+WHERE (%(cast_time)s>=%%s AND %(cast_time)s<%%s)
+ORDER BY COALESCE(t.id,0)=0,t.id""" % {
+          'cast_time': self.env.get_db_cnx().cast('t.time', 'int')})
         self.assertEqual([1217548800, 1220227200], args)
         tickets = query.execute(self.req)
 
 """SELECT t.id AS id,t.summary AS summary,t.time AS time,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.changetime AS changetime,priority.value AS priority_value
 FROM ticket AS t
   LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
-WHERE NOT (""" + exp("t.time") + ">=%s AND " + exp("t.time") + """<%s)
-ORDER BY COALESCE(t.id,0)=0,t.id""")
+WHERE NOT (%(cast_time)s>=%%s AND %(cast_time)s<%%s)
+ORDER BY COALESCE(t.id,0)=0,t.id""" % {
+          'cast_time': self.env.get_db_cnx().cast('t.time', 'int')})
         self.assertEqual([1217548800, 1220227200], args)
         tickets = query.execute(self.req)
 
 """SELECT t.id AS id,t.summary AS summary,t.time AS time,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.changetime AS changetime,priority.value AS priority_value
 FROM ticket AS t
   LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
-WHERE """ + exp("t.time") + """>=%s
-ORDER BY COALESCE(t.id,0)=0,t.id""")
+WHERE %(cast_time)s>=%%s
+ORDER BY COALESCE(t.id,0)=0,t.id""" % {
+          'cast_time': self.env.get_db_cnx().cast('t.time', 'int')})
         self.assertEqual([1217548800], args)
         tickets = query.execute(self.req)
 
 """SELECT t.id AS id,t.summary AS summary,t.time AS time,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.changetime AS changetime,priority.value AS priority_value
 FROM ticket AS t
   LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
-WHERE """ + exp("t.time") + """<%s
-ORDER BY COALESCE(t.id,0)=0,t.id""")
+WHERE %(cast_time)s<%%s
+ORDER BY COALESCE(t.id,0)=0,t.id""" % {
+          'cast_time': self.env.get_db_cnx().cast('t.time', 'int')})
         self.assertEqual([1220227200], args)
         tickets = query.execute(self.req)
 
 """SELECT t.id AS id,t.summary AS summary,t.changetime AS changetime,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.time AS time,priority.value AS priority_value
 FROM ticket AS t
   LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority)
-WHERE (""" + exp("t.changetime") + ">=%s AND " + exp("t.changetime") + """<%s)
-ORDER BY COALESCE(t.id,0)=0,t.id""")
+WHERE (%(cast_changetime)s>=%%s AND %(cast_changetime)s<%%s)
+ORDER BY COALESCE(t.id,0)=0,t.id""" % {
+          'cast_changetime': self.env.get_db_cnx().cast('t.changetime', 'int')})
         self.assertEqual([1217548800, 1220227200], args)
         tickets = query.execute(self.req)
 
 
 
 class QueryLinksTestCase(unittest.TestCase):
+
     def setUp(self):
         self.env = EnvironmentStub(default_data=True)
         self.query_module = QueryModule(self.env)
         req = Mock(perm=MockPerm(), args={}, href=Href('/'))
         self.formatter = LinkFormatter(self.env, Context.from_request(req))
 
+    def tearDown(self):
+        self.env.reset_db()
+
     def _format_link(self, query, label):
         return str(self.query_module._format_link(self.formatter, 'query',
                                                   query, label))

trac/ticket/tests/report.py

     def test_sub_var_quotes(self):
         sql, values, missing_args = self.report_module.sql_sub_vars(
             "'$VAR'", {'VAR': 'value'})
-        self.assertEqual("''||%s||''", sql)
+        self.assertEqual(self.env.get_db_cnx().concat("''", '%s', "''"), sql)
         self.assertEqual(['value'], values)
         self.assertEqual([], missing_args)
 
+    # Probably not needed anymore
     def test_sub_var_mysql(self):
         env = EnvironmentStub()
-        env.db = MockMySQLConnection()
+        env.db = MockMySQLConnection() # ditto
         sql, values, missing_args = ReportModule(env).sql_sub_vars(
             "'$VAR'", {'VAR': 'value'})
         self.assertEqual("concat('', %s, '')", sql)

trac/ticket/tests/roadmap.py

         prov.config = self.env.config
         self.stats = prov.get_ticket_group_stats([tkt1.id, tkt2.id, tkt3.id])
 
+    def tearDown(self):
+        self.env.reset_db()
+
     def test_stats(self):
         self.assertEquals(self.stats.title, 'ticket status', 'title incorrect')
         self.assertEquals(self.stats.unit, 'ticket', 'unit incorrect')

trac/ticket/tests/wikisyntax.py

                           'status': 'new'})
     ticket.insert()
 
+def ticket_teardown(tc):
+    tc.env.reset_db()
+
 
 
 REPORT_TEST_CASES=u"""
     roo.due = None
     roo.insert()
 
+def milestone_teardown(tc):
+    tc.env.reset_db()
+
+
 
 QUERY_TEST_CASES="""
 ============================== query: link resolver
 
 def suite():
     suite = unittest.TestSuite()
-    suite.addTest(formatter.suite(TICKET_TEST_CASES, ticket_setup, __file__))
+    suite.addTest(formatter.suite(TICKET_TEST_CASES, ticket_setup, __file__,
+                                  ticket_teardown))
     suite.addTest(formatter.suite(REPORT_TEST_CASES, report_setup, __file__))
     suite.addTest(formatter.suite(MILESTONE_TEST_CASES, milestone_setup,
-                                  __file__))
+                                  __file__, milestone_teardown))
     suite.addTest(formatter.suite(QUERY_TEST_CASES, file=__file__))
     suite.addTest(formatter.suite(COMMENT_TEST_CASES, file=__file__))
     return suite

trac/versioncontrol/tests/svn_fs.py

         pool = core.svn_pool_create(None)
         dumpstream = None
         try:
+            if os.path.exists(REPOS_PATH):
+                print 'trouble ahead with db/rep-cache.db... see #8278'
             r = repos.svn_repos_create(REPOS_PATH, '', '', None, None, pool)
             if hasattr(repos, 'svn_repos_load_fs2'):
                 repos.svn_repos_load_fs2(r, dumpfile, StringIO(),

trac/web/tests/auth.py

         self.db = self.env.get_db_cnx()
         self.module = LoginModule(self.env)
 
+    def tearDown(self):
+        self.env.reset_db()
+
     def test_anonymous_access(self):
         req = Mock(incookie=Cookie(), href=Href('/trac.cgi'),
                    remote_addr='127.0.0.1', remote_user=None,

trac/web/tests/session.py

         self.env = EnvironmentStub()
         self.db = self.env.get_db_cnx()
 
+    def tearDown(self):
+        self.env.reset_db()
+
     def test_new_session(self):
         """
         Verify that a session cookie gets sent back to the client for a new

trac/wiki/tests/formatter.py

         self._setup = setup
         self._teardown = teardown
 
-        self.env = EnvironmentStub()
-        wiki = WikiPage(self.env)
-        wiki.name = 'WikiStart'
-        wiki.text = '--'
-        wiki.save('joe', 'Entry page', '::1', datetime.now(utc))
         req = Mock(href=Href('/'), abs_href=Href('http://www.example.com/'),
                    authname='anonymous', perm=MockPerm(), args={})
         if context:
             context = Context.from_request(req, 'wiki', 'WikiStart')
         self.context = context
 
+        self.env = EnvironmentStub()
         # -- macros support
         self.env.path = ''
         # -- intertrac support
         self.env.abs_href = req.abs_href
 
     def setUp(self):
+        wiki = WikiPage(self.env)
+        wiki.name = 'WikiStart'
+        wiki.text = '--'
+        wiki.save('joe', 'Entry page', '::1', datetime.now(utc))
         if self._setup:
             self._setup(self)
 
     def tearDown(self):
+        self.env.reset_db()
         if self._teardown:
             self._teardown(self)
 

trac/wiki/tests/model.py

         self.env = EnvironmentStub()
         self.db = self.env.get_db_cnx()
 
+    def tearDown(self):
+        self.env.reset_db()
+
     def test_new_page(self):
         page = WikiPage(self.env)
         self.assertEqual(False, page.exists)

trac/wiki/tests/wikisyntax.py

     w.text = '--'
     w.save('joe', 'other third level of hierarchy', '::1', now)
 
+def wiki_teardown(tc):
+    tc.env.reset_db()
+
 
 def suite():
     suite = unittest.TestSuite()
-    suite.addTest(formatter.suite(TEST_CASES, wiki_setup, __file__))
+    suite.addTest(formatter.suite(TEST_CASES, wiki_setup, __file__,
+                                  wiki_teardown))
     suite.addTest(formatter.suite(RELATIVE_LINKS_TESTS, wiki_setup, __file__,
+                                  wiki_teardown,
                                   context=('wiki', 'Main/Sub')))
     suite.addTest(formatter.suite(SCOPED_LINKS_TESTS, wiki_setup, __file__,
+                                  wiki_teardown,
                                   context=('wiki', 
                                       'FirstLevel/SecondLevel/ThirdLevel')))
     return suite
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.