tests.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. from django.conf import settings
  2. from django.db import connection, DEFAULT_DB_ALIAS
  3. from django.test import TestCase, skipUnlessDBFeature
  4. from django.utils import functional
  5. from models import Reporter, Article
  6. #
  7. # The introspection module is optional, so methods tested here might raise
  8. # NotImplementedError. This is perfectly acceptable behavior for the backend
  9. # in question, but the tests need to handle this without failing. Ideally we'd
  10. # skip these tests, but until #4788 is done we'll just ignore them.
  11. #
  12. # The easiest way to accomplish this is to decorate every test case with a
  13. # wrapper that ignores the exception.
  14. #
  15. # The metaclass is just for fun.
  16. #
  17. def ignore_not_implemented(func):
  18. def _inner(*args, **kwargs):
  19. try:
  20. return func(*args, **kwargs)
  21. except NotImplementedError:
  22. return None
  23. functional.update_wrapper(_inner, func)
  24. return _inner
  25. class IgnoreNotimplementedError(type):
  26. def __new__(cls, name, bases, attrs):
  27. for k,v in attrs.items():
  28. if k.startswith('test'):
  29. attrs[k] = ignore_not_implemented(v)
  30. return type.__new__(cls, name, bases, attrs)
  31. class IntrospectionTests(TestCase):
  32. __metaclass__ = IgnoreNotimplementedError
  33. def test_table_names(self):
  34. tl = connection.introspection.table_names()
  35. self.assertTrue(Reporter._meta.db_table in tl,
  36. "'%s' isn't in table_list()." % Reporter._meta.db_table)
  37. self.assertTrue(Article._meta.db_table in tl,
  38. "'%s' isn't in table_list()." % Article._meta.db_table)
  39. def test_django_table_names(self):
  40. cursor = connection.cursor()
  41. cursor.execute('CREATE TABLE django_ixn_test_table (id INTEGER);');
  42. tl = connection.introspection.django_table_names()
  43. cursor.execute("DROP TABLE django_ixn_test_table;")
  44. self.assertTrue('django_ixn_testcase_table' not in tl,
  45. "django_table_names() returned a non-Django table")
  46. def test_installed_models(self):
  47. tables = [Article._meta.db_table, Reporter._meta.db_table]
  48. models = connection.introspection.installed_models(tables)
  49. self.assertEqual(models, set([Article, Reporter]))
  50. def test_sequence_list(self):
  51. sequences = connection.introspection.sequence_list()
  52. expected = {'table': Reporter._meta.db_table, 'column': 'id'}
  53. self.assertTrue(expected in sequences,
  54. 'Reporter sequence not found in sequence_list()')
  55. def test_get_table_description_names(self):
  56. cursor = connection.cursor()
  57. desc = connection.introspection.get_table_description(cursor, Reporter._meta.db_table)
  58. self.assertEqual([r[0] for r in desc],
  59. [f.column for f in Reporter._meta.fields])
  60. def test_get_table_description_types(self):
  61. cursor = connection.cursor()
  62. desc = connection.introspection.get_table_description(cursor, Reporter._meta.db_table)
  63. self.assertEqual(
  64. [datatype(r[1], r) for r in desc],
  65. ['IntegerField', 'CharField', 'CharField', 'CharField', 'BigIntegerField']
  66. )
  67. # Regression test for #9991 - 'real' types in postgres
  68. @skipUnlessDBFeature('has_real_datatype')
  69. def test_postgresql_real_type(self):
  70. cursor = connection.cursor()
  71. cursor.execute("CREATE TABLE django_ixn_real_test_table (number REAL);")
  72. desc = connection.introspection.get_table_description(cursor, 'django_ixn_real_test_table')
  73. cursor.execute('DROP TABLE django_ixn_real_test_table;')
  74. self.assertEqual(datatype(desc[0][1], desc[0]), 'FloatField')
  75. def test_get_relations(self):
  76. cursor = connection.cursor()
  77. relations = connection.introspection.get_relations(cursor, Article._meta.db_table)
  78. # Older versions of MySQL don't have the chops to report on this stuff,
  79. # so just skip it if no relations come back. If they do, though, we
  80. # should test that the response is correct.
  81. if relations:
  82. # That's {field_index: (field_index_other_table, other_table)}
  83. self.assertEqual(relations, {3: (0, Reporter._meta.db_table)})
  84. def test_get_indexes(self):
  85. cursor = connection.cursor()
  86. indexes = connection.introspection.get_indexes(cursor, Article._meta.db_table)
  87. self.assertEqual(indexes['reporter_id'], {'unique': False, 'primary_key': False})
  88. def datatype(dbtype, description):
  89. """Helper to convert a data type into a string."""
  90. dt = connection.introspection.get_field_type(dbtype, description)
  91. if type(dt) is tuple:
  92. return dt[0]
  93. else:
  94. return dt