@@ -55,6 +55,40 @@ def check_triggers(connection, table, expected, present=True):
5555 else :
5656 assert item not in triggers
5757
58+
59+ def check_orm_actual_tables_match (engine , orm_table , schema_name = get_schema_name ()):
60+ """Check that table defined in ORM matches the actual table in the database.
61+ This method is useful in smoke tests."""
62+
63+ # Check actual table existence
64+ names = set (get_schema_item_names (engine , "tables" , schema_name = schema_name ))
65+ assert orm_table .__tablename__ in names
66+
67+ # Reflect table
68+ metadata = MetaData (schema = schema_name , bind = engine )
69+ actual_table = Table (orm_table .__tablename__ , metadata , autoload_with = engine )
70+
71+ # Check that table columns match
72+ def type_match (class1 , class2 ):
73+ return (
74+ # This is usually the case if they match
75+ issubclass (class1 , class2 )
76+ or issubclass (class2 , class1 )
77+ # Ad-hocery around dialect vs non-dialect types
78+ or all (issubclass (c , sqltypes ._AbstractInterval ) for c in (class1 , class2 ))
79+ )
80+
81+ # This checks column order as well as type.
82+ for actual_col , orm_col in zip (actual_table .columns , orm_table .__table__ .columns ):
83+ assert actual_col .name == orm_col .name
84+ # print(
85+ # f"{actual_col.name}: actual {actual_col.type.__class__} orm: {orm_col.type.__class__}"
86+ # )
87+ assert type_match (
88+ actual_col .type .__class__ , orm_col .type .__class__
89+ ), f"{ actual_col .name } : actual { actual_col .type .__class__ } orm: { orm_col .type .__class__ } "
90+
91+
5892def check_history_tracking_upgrade (
5993 connection : Connection ,
6094 table_name : str ,
0 commit comments