Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 692 lines (526 sloc) 24.696 kb
8f88045 added mysql unit tests
Michael Kleehammer authored
1 #!/usr/bin/python
2 # -*- coding: latin-1 -*-
3
4 usage = """\
5 usage: %prog [options] connection_string
6
95b11a2 removed MySQL BIT tests - not behaving as bools
Michael Kleehammer authored
7 Unit tests for MySQL. To use, pass a connection string as the parameter. The tests will create and drop tables t1 and
8 t2 as necessary. The default installation of mysql allows you to connect locally with no password and already contains
9 a 'test' database, so you can probably use the following. (Update the driver name as appropriate.)
10
11 ./mysqltests DRIVER={MySQL};DATABASE=test
8f88045 added mysql unit tests
Michael Kleehammer authored
12
13 These tests use the pyodbc library from the build directory, not the version installed in your
14 Python directories. You must run `python setup.py build` before running these tests.
15 """
16
17 import sys, os, re
18 import unittest
19 from decimal import Decimal
20 from datetime import datetime, date, time
95b11a2 removed MySQL BIT tests - not behaving as bools
Michael Kleehammer authored
21 from os.path import join, getsize, dirname, abspath, basename
8f88045 added mysql unit tests
Michael Kleehammer authored
22 from testutils import *
23
24 _TESTSTR = '0123456789-abcdefghijklmnopqrstuvwxyz-'
25
26 def _generate_test_string(length):
27 """
28 Returns a string of composed of `seed` to make a string `length` characters long.
29
30 To enhance performance, there are 3 ways data is read, based on the length of the value, so most data types are
31 tested with 3 lengths. This function helps us generate the test data.
32
33 We use a recognizable data set instead of a single character to make it less likely that "overlap" errors will
34 be hidden and to help us manually identify where a break occurs.
35 """
36 if length <= len(_TESTSTR):
37 return _TESTSTR[:length]
38
39 c = (length + len(_TESTSTR)-1) / len(_TESTSTR)
40 v = _TESTSTR * c
41 return v[:length]
42
43 class MySqlTestCase(unittest.TestCase):
44
45 SMALL_FENCEPOST_SIZES = [ 0, 1, 255, 256, 510, 511, 512, 1023, 1024, 2047, 2048, 4000 ]
46 LARGE_FENCEPOST_SIZES = [ 4095, 4096, 4097, 10 * 1024, 20 * 1024 ]
47
48 ANSI_FENCEPOSTS = [ _generate_test_string(size) for size in SMALL_FENCEPOST_SIZES ]
49 UNICODE_FENCEPOSTS = [ unicode(s) for s in ANSI_FENCEPOSTS ]
50 BLOB_FENCEPOSTS = ANSI_FENCEPOSTS + [ _generate_test_string(size) for size in LARGE_FENCEPOST_SIZES ]
51
52 def __init__(self, method_name, connection_string):
53 unittest.TestCase.__init__(self, method_name)
54 self.connection_string = connection_string
55
56 def setUp(self):
57 self.cnxn = pyodbc.connect(self.connection_string)
58 self.cursor = self.cnxn.cursor()
59
60 for i in range(3):
61 try:
62 self.cursor.execute("drop table t%d" % i)
63 self.cnxn.commit()
64 except:
65 pass
66
67 for i in range(3):
68 try:
69 self.cursor.execute("drop procedure proc%d" % i)
70 self.cnxn.commit()
71 except:
72 pass
73
74 self.cnxn.rollback()
75
76 def tearDown(self):
77 try:
78 self.cursor.close()
79 self.cnxn.close()
80 except:
81 # If we've already closed the cursor or connection, exceptions are thrown.
82 pass
83
84 def test_multiple_bindings(self):
85 "More than one bind and select on a cursor"
86 self.cursor.execute("create table t1(n int)")
87 self.cursor.execute("insert into t1 values (?)", 1)
88 self.cursor.execute("insert into t1 values (?)", 2)
89 self.cursor.execute("insert into t1 values (?)", 3)
90 for i in range(3):
91 self.cursor.execute("select n from t1 where n < ?", 10)
92 self.cursor.execute("select n from t1 where n < 3")
93
94
95 def test_different_bindings(self):
96 self.cursor.execute("create table t1(n int)")
97 self.cursor.execute("create table t2(d datetime)")
98 self.cursor.execute("insert into t1 values (?)", 1)
99 self.cursor.execute("insert into t2 values (?)", datetime.now())
100
101 def test_datasources(self):
102 p = pyodbc.dataSources()
103 self.assert_(isinstance(p, dict))
104
105 def test_getinfo_string(self):
106 value = self.cnxn.getinfo(pyodbc.SQL_CATALOG_NAME_SEPARATOR)
107 self.assert_(isinstance(value, str))
108
109 def test_getinfo_bool(self):
110 value = self.cnxn.getinfo(pyodbc.SQL_ACCESSIBLE_TABLES)
111 self.assert_(isinstance(value, bool))
112
113 def test_getinfo_int(self):
114 value = self.cnxn.getinfo(pyodbc.SQL_DEFAULT_TXN_ISOLATION)
115 self.assert_(isinstance(value, (int, long)))
116
117 def test_getinfo_smallint(self):
118 value = self.cnxn.getinfo(pyodbc.SQL_CONCAT_NULL_BEHAVIOR)
119 self.assert_(isinstance(value, int))
120
121 def _test_strtype(self, sqltype, value, colsize=None):
122 """
123 The implementation for string, Unicode, and binary tests.
124 """
125 assert colsize is None or (value is None or colsize >= len(value))
126
127 if colsize:
128 sql = "create table t1(s %s(%s))" % (sqltype, colsize)
129 else:
130 sql = "create table t1(s %s)" % sqltype
131
132 try:
133 self.cursor.execute(sql)
134 except:
135 print '>>>>', sql
136 self.cursor.execute("insert into t1 values(?)", value)
137 v = self.cursor.execute("select * from t1").fetchone()[0]
a64f284 More Unicode fixes. Updated mysql tests.
Michael Kleehammer authored
138
139 # Removing this check for now until I get the charset working properly.
140 # If we use latin1, results are 'str' instead of 'unicode', which would be
141 # correct. Setting charset to ucs-2 causes a crash in SQLGetTypeInfo(SQL_DATETIME).
142 # self.assertEqual(type(v), type(value))
8f88045 added mysql unit tests
Michael Kleehammer authored
143
144 if value is not None:
145 self.assertEqual(len(v), len(value))
146
147 self.assertEqual(v, value)
148
149 #
150 # varchar
151 #
152
153 def test_varchar_null(self):
154 self._test_strtype('varchar', None, 100)
155
156 # Generate a test for each fencepost size: test_varchar_0, etc.
157 def _maketest(value):
158 def t(self):
159 self._test_strtype('varchar', value, max(1, len(value)))
160 return t
161 for value in ANSI_FENCEPOSTS:
162 locals()['test_varchar_%s' % len(value)] = _maketest(value)
163
a64f284 More Unicode fixes. Updated mysql tests.
Michael Kleehammer authored
164 # Generate a test using Unicode.
165 for value in UNICODE_FENCEPOSTS:
166 locals()['test_wvarchar_%s' % len(value)] = _maketest(value)
167
8f88045 added mysql unit tests
Michael Kleehammer authored
168 def test_varchar_many(self):
169 self.cursor.execute("create table t1(c1 varchar(300), c2 varchar(300), c3 varchar(300))")
170
171 v1 = 'ABCDEFGHIJ' * 30
172 v2 = '0123456789' * 30
173 v3 = '9876543210' * 30
174
175 self.cursor.execute("insert into t1(c1, c2, c3) values (?,?,?)", v1, v2, v3);
176 row = self.cursor.execute("select c1, c2, c3 from t1").fetchone()
177
178 self.assertEqual(v1, row.c1)
179 self.assertEqual(v2, row.c2)
180 self.assertEqual(v3, row.c3)
181
182 def test_varchar_upperlatin(self):
183 self._test_strtype('varchar', 'á', colsize=3)
184
185 #
186 # binary
187 #
188
189 def test_null_binary(self):
190 self._test_strtype('varbinary', None, 100)
191
192 def test_large_null_binary(self):
193 # Bug 1575064
194 self._test_strtype('varbinary', None, 4000)
195
a64f284 More Unicode fixes. Updated mysql tests.
Michael Kleehammer authored
196 # Generate a test for each fencepost size: test_binary_0, etc.
8f88045 added mysql unit tests
Michael Kleehammer authored
197 def _maketest(value):
198 def t(self):
199 self._test_strtype('varbinary', buffer(value), max(1, len(value)))
200 return t
201 for value in ANSI_FENCEPOSTS:
202 locals()['test_binary_%s' % len(value)] = _maketest(value)
203
204 #
205 # blob
206 #
207
208 def test_blob_null(self):
209 self._test_strtype('blob', None)
210
a64f284 More Unicode fixes. Updated mysql tests.
Michael Kleehammer authored
211 # Generate a test for each fencepost size: test_blob_0, etc.
8f88045 added mysql unit tests
Michael Kleehammer authored
212 def _maketest(value):
213 def t(self):
214 self._test_strtype('blob', buffer(value))
215 return t
216 for value in BLOB_FENCEPOSTS:
217 locals()['test_blob_%s' % len(value)] = _maketest(value)
218
219 def test_blob_upperlatin(self):
220 self._test_strtype('blob', buffer('á'))
221
222 #
223 # text
224 #
225
226 def test_null_text(self):
227 self._test_strtype('text', None)
228
a64f284 More Unicode fixes. Updated mysql tests.
Michael Kleehammer authored
229 # Generate a test for each fencepost size: test_text_0, etc.
8f88045 added mysql unit tests
Michael Kleehammer authored
230 def _maketest(value):
231 def t(self):
232 self._test_strtype('text', value)
233 return t
234 for value in ANSI_FENCEPOSTS:
235 locals()['test_text_%s' % len(value)] = _maketest(value)
236
237 def test_text_upperlatin(self):
238 self._test_strtype('text', 'á')
239
240 #
a64f284 More Unicode fixes. Updated mysql tests.
Michael Kleehammer authored
241 # unicode
242 #
243
244 def test_unicode_query(self):
245 self.cursor.execute(u"select 1")
246
247 #
8f88045 added mysql unit tests
Michael Kleehammer authored
248 # bit
249 #
250
95b11a2 removed MySQL BIT tests - not behaving as bools
Michael Kleehammer authored
251 # The MySQL driver maps BIT colums to the ODBC bit data type, but they aren't behaving quite like a Boolean value
252 # (which is what the ODBC bit data type really represents). The MySQL BOOL data type is just an alias for a small
253 # integer, so pyodbc can't recognize it and map it back to True/False.
254 #
255 # You can use both BIT and BOOL and they will act as you expect if you treat them as integers. You can write 0 and
256 # 1 to them and they will work.
257
258 # def test_bit(self):
259 # value = True
260 # self.cursor.execute("create table t1(b bit)")
261 # self.cursor.execute("insert into t1 values (?)", value)
262 # v = self.cursor.execute("select b from t1").fetchone()[0]
263 # self.assertEqual(type(v), bool)
264 # self.assertEqual(v, value)
265 #
266 # def test_bit_string_true(self):
267 # self.cursor.execute("create table t1(b bit)")
268 # self.cursor.execute("insert into t1 values (?)", "xyzzy")
269 # v = self.cursor.execute("select b from t1").fetchone()[0]
270 # self.assertEqual(type(v), bool)
271 # self.assertEqual(v, True)
272 #
273 # def test_bit_string_false(self):
274 # self.cursor.execute("create table t1(b bit)")
275 # self.cursor.execute("insert into t1 values (?)", "")
276 # v = self.cursor.execute("select b from t1").fetchone()[0]
277 # self.assertEqual(type(v), bool)
278 # self.assertEqual(v, False)
279
8f88045 added mysql unit tests
Michael Kleehammer authored
280 #
281 # decimal
282 #
283
284 def test_small_decimal(self):
285 # value = Decimal('1234567890987654321')
286 value = Decimal('100010') # (I use this because the ODBC docs tell us how the bytes should look in the C struct)
287 self.cursor.execute("create table t1(d numeric(19))")
288 self.cursor.execute("insert into t1 values(?)", value)
289 v = self.cursor.execute("select * from t1").fetchone()[0]
290 self.assertEqual(type(v), Decimal)
291 self.assertEqual(v, value)
292
293
294 def test_small_decimal_scale(self):
295 # The same as small_decimal, except with a different scale. This value exactly matches the ODBC documentation
296 # example in the C Data Types appendix.
297 value = '1000.10'
298 value = Decimal(value)
299 self.cursor.execute("create table t1(d numeric(20,6))")
300 self.cursor.execute("insert into t1 values(?)", value)
301 v = self.cursor.execute("select * from t1").fetchone()[0]
302 self.assertEqual(type(v), Decimal)
303 self.assertEqual(v, value)
304
305
306 def test_negative_decimal_scale(self):
307 value = Decimal('-10.0010')
308 self.cursor.execute("create table t1(d numeric(19,4))")
309 self.cursor.execute("insert into t1 values(?)", value)
310 v = self.cursor.execute("select * from t1").fetchone()[0]
311 self.assertEqual(type(v), Decimal)
312 self.assertEqual(v, value)
313
314 def test_subquery_params(self):
315 """Ensure parameter markers work in a subquery"""
316 self.cursor.execute("create table t1(id integer, s varchar(20))")
317 self.cursor.execute("insert into t1 values (?,?)", 1, 'test')
318 row = self.cursor.execute("""
319 select x.id
320 from (
321 select id
322 from t1
323 where s = ?
324 and id between ? and ?
325 ) x
326 """, 'test', 1, 10).fetchone()
327 self.assertNotEqual(row, None)
328 self.assertEqual(row[0], 1)
329
330 def _exec(self):
331 self.cursor.execute(self.sql)
332
333 def test_close_cnxn(self):
334 """Make sure using a Cursor after closing its connection doesn't crash."""
335
336 self.cursor.execute("create table t1(id integer, s varchar(20))")
337 self.cursor.execute("insert into t1 values (?,?)", 1, 'test')
338 self.cursor.execute("select * from t1")
339
340 self.cnxn.close()
341
342 # Now that the connection is closed, we expect an exception. (If the code attempts to use
343 # the HSTMT, we'll get an access violation instead.)
344 self.sql = "select * from t1"
345 self.assertRaises(pyodbc.ProgrammingError, self._exec)
346
347 def test_empty_string(self):
348 self.cursor.execute("create table t1(s varchar(20))")
349 self.cursor.execute("insert into t1 values(?)", "")
350
351 def test_fixed_str(self):
352 value = "testing"
353 self.cursor.execute("create table t1(s char(7))")
354 self.cursor.execute("insert into t1 values(?)", "testing")
355 v = self.cursor.execute("select * from t1").fetchone()[0]
356 self.assertEqual(type(v), str)
357 self.assertEqual(len(v), len(value)) # If we alloc'd wrong, the test below might work because of an embedded NULL
358 self.assertEqual(v, value)
359
360 def test_negative_row_index(self):
361 self.cursor.execute("create table t1(s varchar(20))")
362 self.cursor.execute("insert into t1 values(?)", "1")
363 row = self.cursor.execute("select * from t1").fetchone()
364 self.assertEquals(row[0], "1")
365 self.assertEquals(row[-1], "1")
366
367 def test_version(self):
368 self.assertEquals(3, len(pyodbc.version.split('.'))) # 1.3.1 etc.
369
370 #
371 # date, time, datetime
372 #
373
374 def test_datetime(self):
375 value = datetime(2007, 1, 15, 3, 4, 5)
376
377 self.cursor.execute("create table t1(dt datetime)")
378 self.cursor.execute("insert into t1 values (?)", value)
379
380 result = self.cursor.execute("select dt from t1").fetchone()[0]
381 self.assertEquals(value, result)
382
383 def test_date(self):
384 value = date(2001, 1, 1)
385
386 self.cursor.execute("create table t1(dt date)")
387 self.cursor.execute("insert into t1 values (?)", value)
388
389 result = self.cursor.execute("select dt from t1").fetchone()[0]
390 self.assertEquals(type(result), type(value))
391 self.assertEquals(result, value)
392
393 #
394 # ints and floats
395 #
396
397 def test_int(self):
398 value = 1234
399 self.cursor.execute("create table t1(n int)")
400 self.cursor.execute("insert into t1 values (?)", value)
401 result = self.cursor.execute("select n from t1").fetchone()[0]
402 self.assertEquals(result, value)
403
404 def test_negative_int(self):
405 value = -1
406 self.cursor.execute("create table t1(n int)")
407 self.cursor.execute("insert into t1 values (?)", value)
408 result = self.cursor.execute("select n from t1").fetchone()[0]
409 self.assertEquals(result, value)
410
411 def test_bigint(self):
a64f284 More Unicode fixes. Updated mysql tests.
Michael Kleehammer authored
412
413 # This fails on 64-bit Fedora with 5.1.
414 # Should return 0x0123456789
415 # Does return 0x0000000000
416 #
417 # Top 4 bytes are returned as 0x00 00 00 00. If the input is high enough, they are returned as 0xFF FF FF FF.
418 input = 0x123456789
419 print 'writing %x' % input
8f88045 added mysql unit tests
Michael Kleehammer authored
420 self.cursor.execute("create table t1(d bigint)")
421 self.cursor.execute("insert into t1 values (?)", input)
422 result = self.cursor.execute("select d from t1").fetchone()[0]
423 self.assertEqual(result, input)
424
425 def test_float(self):
426 value = 1234.5
427 self.cursor.execute("create table t1(n float)")
428 self.cursor.execute("insert into t1 values (?)", value)
429 result = self.cursor.execute("select n from t1").fetchone()[0]
430 self.assertEquals(result, value)
431
432 def test_negative_float(self):
433 value = -200
434 self.cursor.execute("create table t1(n float)")
435 self.cursor.execute("insert into t1 values (?)", value)
436 result = self.cursor.execute("select n from t1").fetchone()[0]
437 self.assertEqual(value, result)
438
439
440 def test_date(self):
441 value = date.today()
442
443 self.cursor.execute("create table t1(d date)")
444 self.cursor.execute("insert into t1 values (?)", value)
445
446 result = self.cursor.execute("select d from t1").fetchone()[0]
447 self.assertEquals(value, result)
448
449
450 def test_time(self):
451 value = datetime.now().time()
452
453 # We aren't yet writing values using the new extended time type so the value written to the database is only
454 # down to the second.
455 value = value.replace(microsecond=0)
456
457 self.cursor.execute("create table t1(t time)")
458 self.cursor.execute("insert into t1 values (?)", value)
459
460 result = self.cursor.execute("select t from t1").fetchone()[0]
461 self.assertEquals(value, result)
462
463 #
464 # misc
465 #
466
467 def test_rowcount_delete(self):
468 self.assertEquals(self.cursor.rowcount, -1)
469 self.cursor.execute("create table t1(i int)")
470 count = 4
471 for i in range(count):
472 self.cursor.execute("insert into t1 values (?)", i)
473 self.cursor.execute("delete from t1")
474 self.assertEquals(self.cursor.rowcount, count)
475
476 def test_rowcount_nodata(self):
477 """
478 This represents a different code path than a delete that deleted something.
479
480 The return value is SQL_NO_DATA and code after it was causing an error. We could use SQL_NO_DATA to step over
481 the code that errors out and drop down to the same SQLRowCount code. On the other hand, we could hardcode a
482 zero return value.
483 """
484 self.cursor.execute("create table t1(i int)")
485 # This is a different code path internally.
486 self.cursor.execute("delete from t1")
487 self.assertEquals(self.cursor.rowcount, 0)
488
489 def test_rowcount_select(self):
490 """
491 Ensure Cursor.rowcount is set properly after a select statement.
492
493 pyodbc calls SQLRowCount after each execute and sets Cursor.rowcount. Databases can return the actual rowcount
494 or they can return -1 if it would help performance. MySQL seems to always return the correct rowcount.
495 """
496 self.cursor.execute("create table t1(i int)")
497 count = 4
498 for i in range(count):
499 self.cursor.execute("insert into t1 values (?)", i)
500 self.cursor.execute("select * from t1")
501 self.assertEquals(self.cursor.rowcount, count)
502
503 rows = self.cursor.fetchall()
504 self.assertEquals(len(rows), count)
505 self.assertEquals(self.cursor.rowcount, count)
506
507 def test_rowcount_reset(self):
508 "Ensure rowcount is reset to -1"
509
510 # The Python DB API says that rowcount should be set to -1 and most ODBC drivers let us know there are no
511 # records. MySQL always returns 0, however. Without parsing the SQL (which we are not going to do), I'm not
512 # sure how we can tell the difference and set the value to -1. For now, I'll have this test check for 0.
513
514 self.cursor.execute("create table t1(i int)")
515 count = 4
516 for i in range(count):
517 self.cursor.execute("insert into t1 values (?)", i)
518 self.assertEquals(self.cursor.rowcount, 1)
519
520 self.cursor.execute("create table t2(i int)")
521 self.assertEquals(self.cursor.rowcount, 0)
522
523 def test_lower_case(self):
524 "Ensure pyodbc.lowercase forces returned column names to lowercase."
525
526 # Has to be set before creating the cursor, so we must recreate self.cursor.
527
528 pyodbc.lowercase = True
529 self.cursor = self.cnxn.cursor()
530
531 self.cursor.execute("create table t1(Abc int, dEf int)")
532 self.cursor.execute("select * from t1")
533
534 names = [ t[0] for t in self.cursor.description ]
535 names.sort()
536
537 self.assertEquals(names, [ "abc", "def" ])
538
539 # Put it back so other tests don't fail.
540 pyodbc.lowercase = False
541
542 def test_row_description(self):
543 """
544 Ensure Cursor.description is accessible as Row.cursor_description.
545 """
546 self.cursor = self.cnxn.cursor()
547 self.cursor.execute("create table t1(a int, b char(3))")
548 self.cnxn.commit()
549 self.cursor.execute("insert into t1 values(1, 'abc')")
550
551 row = self.cursor.execute("select * from t1").fetchone()
552 self.assertEquals(self.cursor.description, row.cursor_description)
553
554
555 def test_executemany(self):
556 self.cursor.execute("create table t1(a int, b varchar(10))")
557
558 params = [ (i, str(i)) for i in range(1, 6) ]
559
560 self.cursor.executemany("insert into t1(a, b) values (?,?)", params)
561
562 count = self.cursor.execute("select count(*) from t1").fetchone()[0]
563 self.assertEqual(count, len(params))
564
565 self.cursor.execute("select a, b from t1 order by a")
566 rows = self.cursor.fetchall()
567 self.assertEqual(count, len(rows))
568
569 for param, row in zip(params, rows):
570 self.assertEqual(param[0], row[0])
571 self.assertEqual(param[1], row[1])
572
573
574 def test_executemany_one(self):
575 "Pass executemany a single sequence"
576 self.cursor.execute("create table t1(a int, b varchar(10))")
577
578 params = [ (1, "test") ]
579
580 self.cursor.executemany("insert into t1(a, b) values (?,?)", params)
581
582 count = self.cursor.execute("select count(*) from t1").fetchone()[0]
583 self.assertEqual(count, len(params))
584
585 self.cursor.execute("select a, b from t1 order by a")
586 rows = self.cursor.fetchall()
587 self.assertEqual(count, len(rows))
588
589 for param, row in zip(params, rows):
590 self.assertEqual(param[0], row[0])
591 self.assertEqual(param[1], row[1])
592
593
594 # REVIEW: The following fails. Research.
595
596 # def test_executemany_failure(self):
597 # """
598 # Ensure that an exception is raised if one query in an executemany fails.
599 # """
600 # self.cursor.execute("create table t1(a int, b varchar(10))")
601 #
602 # params = [ (1, 'good'),
603 # ('error', 'not an int'),
604 # (3, 'good') ]
605 #
606 # self.failUnlessRaises(pyodbc.Error, self.cursor.executemany, "insert into t1(a, b) value (?, ?)", params)
607
608
609 def test_row_slicing(self):
610 self.cursor.execute("create table t1(a int, b int, c int, d int)");
611 self.cursor.execute("insert into t1 values(1,2,3,4)")
612
613 row = self.cursor.execute("select * from t1").fetchone()
614
615 result = row[:]
616 self.failUnless(result is row)
617
618 result = row[:-1]
619 self.assertEqual(result, (1,2,3))
620
621 result = row[0:4]
622 self.failUnless(result is row)
623
624
625 def test_row_repr(self):
626 self.cursor.execute("create table t1(a int, b int, c int, d int)");
627 self.cursor.execute("insert into t1 values(1,2,3,4)")
628
629 row = self.cursor.execute("select * from t1").fetchone()
630
631 result = str(row)
632 self.assertEqual(result, "(1, 2, 3, 4)")
633
634 result = str(row[:-1])
635 self.assertEqual(result, "(1, 2, 3)")
636
637 result = str(row[:1])
638 self.assertEqual(result, "(1,)")
639
640
641 def test_autocommit(self):
642 self.assertEqual(self.cnxn.autocommit, False)
643
644 othercnxn = pyodbc.connect(self.connection_string, autocommit=True)
645 self.assertEqual(othercnxn.autocommit, True)
646
647 othercnxn.autocommit = False
648 self.assertEqual(othercnxn.autocommit, False)
649
650
651 def main():
652 from optparse import OptionParser
653 parser = OptionParser(usage=usage)
654 parser.add_option("-v", "--verbose", action="count", help="Increment test verbosity (can be used multiple times)")
655 parser.add_option("-d", "--debug", action="store_true", default=False, help="Print debugging items")
656 parser.add_option("-t", "--test", help="Run only the named test")
657
658 (options, args) = parser.parse_args()
659
660 if len(args) > 1:
661 parser.error('Only one argument is allowed. Do you need quotes around the connection string?')
662
663 if not args:
95b11a2 removed MySQL BIT tests - not behaving as bools
Michael Kleehammer authored
664 filename = basename(sys.argv[0])
665 assert filename.endswith('.py')
666 connection_string = load_setup_connection_string(filename[:-3])
8f88045 added mysql unit tests
Michael Kleehammer authored
667
668 if not connection_string:
669 parser.print_help()
670 raise SystemExit()
671 else:
672 connection_string = args[0]
673
674 cnxn = pyodbc.connect(connection_string)
675 print_library_info(cnxn)
676 cnxn.close()
677
678 suite = load_tests(MySqlTestCase, options.test, connection_string)
679
680 testRunner = unittest.TextTestRunner(verbosity=options.verbose)
681 result = testRunner.run(suite)
682
683
684 if __name__ == '__main__':
685
686 # Add the build directory to the path so we're testing the latest build, not the installed version.
687
688 add_to_path()
689
690 import pyodbc
691 main()
Something went wrong with that request. Please try again.