Skip to content

Add unit test infrastructure (311 tests, 94% coverage)#16

Open
douglas wants to merge 9 commits intomasterfrom
add-unit-test-infrastructure
Open

Add unit test infrastructure (311 tests, 94% coverage)#16
douglas wants to merge 9 commits intomasterfrom
add-unit-test-infrastructure

Conversation

@douglas
Copy link

@douglas douglas commented Mar 13, 2026

Summary

  • Adds a full unit test suite (test/unit/) covering ~94% of the codebase without requiring any live database connection
  • 311 tests across 34 test files covering the type system, quoting, SQL generation, schema statements, adapters, concerns, and connection setup
  • Fixes a TypeError in PostgreSQLODBCAdapter#create_database (string concatenation with sum)

What was added

Infrastructure

  • test/unit_test_helper.rb — lightweight helper requiring only source files; stubs the ODBC C extension so tests run in any environment
  • Rakefiletest:unit task for fast offline runs, test:all to run both unit and integration

Test files (34 new/expanded)

  • Type system: variant_test, object_test, array_of_test, snowflake_integer_test, snowflake_variant_test, type_test
  • Core: registry_test, error_test, column_test, quoting_test
  • Database statements: dbms_type_cast_test, case_formatting_test, bind_params_test, nullability_test, misc_test, transactions_test
  • Metadata: database_metadata_test, column_metadata_test, connection_setup_test, database_limits_test
  • Schema statements: snowflake_helpers_test, columns_test, indexes_test, tables_test, primary_key_test, foreign_keys_test
  • Concerns: easy_identified_test, insert_attribute_stripper_test
  • Adapters: snowflake_test, mysql_test, postgresql_test, null_test

Test plan

  • rake test:unit — all 311 unit tests pass, no DB connection needed
  • rake test — existing integration tests unchanged (requires live ODBC connection)
  • No new gem dependencies introduced

douglas added 9 commits March 13, 2026 14:47
…onfig

- Add rake test:unit (no DB), test:all tasks to Rakefile
- Relax rake/rubocop version pins in gemspec to match installed versions
- Add ostruct dev dependency for Ruby 4.0 forward compatibility
- Update .rubocop.yml: rename Metrics/LineLength to Layout/LineLength, bump TargetRubyVersion 2.2 to 3.4
…y, errors, column)

- unit_test_helper.rb: stubs ODBC module with SQL type constants, ODBC_UTF8 alias, StubConnection/Driver/Database, and minimal AR ODBCAdapter stub parent class
- Batch 1: Variant, SnowflakeObject, ArrayOf, SnowflakeInteger, SnowflakeVariant type tests
- Registry pattern matching (mysql/postgres/snowflake/unknown/custom)
- Error class hierarchy (QueryTimeoutError, ConnectionFailedError < StatementInvalid)
- Column custom kwargs (native_type, auto_incremented) with AR 8.1 Deduplicable workaround
- Quoting: quote_string, quote_column_name (upcase/mixed-case), quote_hash/array (OBJECT_CONSTRUCT/ARRAY_CONSTRUCT), quote dispatch for Hash/Array/SnowflakeVariant
- dbms_type_cast: all SQL type codes to Ruby types (string/numeric/bool/date/time/binary)
- case formatting: format_case and native_case with upcase/non-upcase identifiers
- bind_params: dollar-sign substitution with multiple binds
- nullability: id always false, SQL_NO_NULLS/SQL_NULLABLE/string YES/NO handling
…bclasses)

- DatabaseMetadata: dynamic accessors, upcase_identifiers?, adapter_class delegation
- ColumnMetadata: type mapping, text picks largest, decimal omits limit (Struct stubs to handle .nil? in ensure)
- ConnectionSetup: DSN and conn_str paths, encoding selection
- DatabaseLimits: table_alias_length returns max of identifier/table_name lengths
- EasyIdentified concern: auto-generate ID path, sequence query
- InsertAttributeStripper concern: variant/object/array column stripping on new records
- Adapter subclasses: Snowflake/Null/MySQL/PostgreSQL flags, quoting, sequence names
- SchemaStatements: extract_default_from_snowflake (nil/strings/booleans/numbers/sequences), extract_data_type_from_snowflake (NUMBER/TIMESTAMP_*/TEXT/FIXED), extract_column_size_from_snowflake (hardcoded sizes for temporal/float/bool, parsed for varchar), construct_sql_type, name_regex
- README: document three-tier test setup (rake test:unit, rake test, rake test:all)
- Add frozen_string_literal comments to all 25 unit test files
- Fix Lint/MissingSuper in ODBCAdapter stub with explanatory comment
- Fix Metrics/ParameterLists in ColumnTest#build_column (6 params -> 4 via **col_opts)
- Fix method-redefined warning in EasyIdentifiedTest via prepend instead of redef
New test files:
- database_statements/transactions_test.rb — begin/commit/rollback autocommit
- database_statements/misc_test.rb — write_query?, handle_query_preprocessing,
  default_sequence_name, empty_insert_statement_value, prepare_statement_sub
- type/type_test.rb — ArrayOf* constants, ActiveRecord::Type registrations
- schema_statements/columns_test.rb — full type mapping for all Snowflake types
- schema_statements/indexes_test.rb — ordinal grouping, filtering, unique flag
- schema_statements/foreign_keys_test.rb — FK construction and schema filtering
- schema_statements/tables_test.rb — table listing, filtering, table_filtered? hook

Additions to existing test files:
- quoting_test.rb: quoted_date (Date, Time UTC, DateTime)
- bind_params_test.rb: prepare_statement_sub dollar-param substitution
- column_metadata_test.rb: float, datetime, timestamp, time, date, binary types
- postgresql_test.rb: distinct (ASC/DESC/NULLS stripping), table_filtered?,
  type_cast bytea path
- schema_statements/primary_key_test.rb (NEW): PrimaryKeySchemaHost + 4
  tests covering nil result, column name, wrong-db filter, last-match wins
- schema_statements/indexes_test.rb: IndexNameSchemaHost + 3 truncation
  tests for index_name respecting max_identifier_len; add BaseIndexNameProvider
  module so SchemaStatements#index_name can call super
- schema_statements/columns_test.rb: STRUCT->:object, ARRAY->:array,
  extract_scale_from_snowflake behavior tests
- adapters/postgresql_test.rb: 7 create_database option tests + 3
  insert_sql RETURNING tests; require active_support/core_ext/hash/reverse_merge
- adapters/mysql_test.rb: create_database SQL (default/custom charset/collation)
  + indexes PRIMARY key filter logic
- concerns/insert_attribute_stripper_test.rb: save! path, nil variant not
  stripped, validate:false bypasses guard
- quoting_test.rb: quoted_date local timezone path
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant