|
| 1 | +--- |
| 2 | +description: |
| 3 | +globs: |
| 4 | +alwaysApply: false |
| 5 | +--- |
| 6 | +# Unit Testing Guide for sqlite_to_databricks_uploader.py |
| 7 | + |
| 8 | +This guide outlines how to create simple unit tests for the [databricks-uploader/sqlite_to_databricks_uploader.py](mdc:databricks-uploader/sqlite_to_databricks_uploader.py) script. The goal is basic functional verification, not exhaustive testing or complex mocking. |
| 9 | + |
| 10 | +## General Approach |
| 11 | + |
| 12 | +1. Use the standard Python `unittest` module. |
| 13 | +2. Create a new test file, e.g., `databricks-uploader/test_uploader.py`. |
| 14 | +3. Focus on testing pure functions or functions with easily verifiable inputs and outputs. |
| 15 | +4. Avoid mocking database connections (SQLite, Databricks) or file system operations if it becomes complex. If a function is heavily reliant on I/O, consider testing its helper components or skipping it for these basic tests. |
| 16 | + |
| 17 | +## Functions to Test & Example Cases |
| 18 | + |
| 19 | +Here are some functions from `sqlite_to_databricks_uploader.py` that are good candidates for simple unit tests: |
| 20 | + |
| 21 | +### 1. `quote_databricks_identifier(name: str) -> str` |
| 22 | + |
| 23 | +* **Purpose**: Tests if identifiers are correctly quoted with backticks and if internal backticks are escaped. |
| 24 | +* **Test Cases**: |
| 25 | + * Input: `"my_table"` -> Expected Output: `"`my_table`"` |
| 26 | + * Input: `"table_with_`_backtick"` -> Expected Output: `"`table_with_``_backtick`"` |
| 27 | + * Input: `123` (as non-string) -> Expected Output: `"`123`"` (ensure it handles and logs conversion) |
| 28 | + |
| 29 | +### 2. `get_qualified_table_name(db_name_for_use_stmt: str, table_name_from_config: str) -> str` |
| 30 | + |
| 31 | +* **Purpose**: Tests the construction of fully qualified table names. |
| 32 | +* **Test Cases**: |
| 33 | + * `db_name_for_use_stmt="mydb"`, `table_name_from_config="mytable"` -> Expected: `"`mydb`"."`mytable`"` |
| 34 | + * `db_name_for_use_stmt="mydb"`, `table_name_from_config="myschema.mytable"` -> Expected: `"`myschema`"."`mytable`"` (and check for potential warning log if `myschema` != `mydb`) |
| 35 | + * `db_name_for_use_stmt=""`, `table_name_from_config="mytable"` -> Expect `ValueError` as per function logic. |
| 36 | + * `db_name_for_use_stmt="mydb"`, `table_name_from_config="my_schema.my_table"` -> Expected: `"`my_schema`"."`my_table`"` |
| 37 | + |
| 38 | +### 3. `parse_args()` |
| 39 | + |
| 40 | +* **Purpose**: Tests if command-line arguments are parsed correctly and defaults are applied. |
| 41 | +* **Test Method**: |
| 42 | + * Import the `parse_args` function. |
| 43 | + * Call `parse_args()` with a list of strings representing command-line arguments (e.g., `parse_args(['--sqlite', 'test.db', '--interval', '60'])`). |
| 44 | + * Assert that the attributes of the returned `Namespace` object have the expected values. |
| 45 | +* **Test Cases**: |
| 46 | + * Test with a minimal set of arguments. |
| 47 | + * Test overriding default values (e.g., `--interval`, `--sqlite-batch-size`). |
| 48 | + * Test boolean flags (e.g., `--once`, `--verbose`). |
| 49 | + * Test that default values are present when arguments are not supplied (e.g., `interval` should default to 30, `sqlite_batch_size` to 1000). |
| 50 | + |
| 51 | +### 4. Placeholder Data Processing Functions |
| 52 | + * `sanitize_data(df: pd.DataFrame, config: dict) -> pd.DataFrame` |
| 53 | + * `filter_data(df: pd.DataFrame, config: dict) -> pd.DataFrame` |
| 54 | + * `aggregate_data(df: pd.DataFrame, config: dict) -> pd.DataFrame` |
| 55 | +* **Purpose**: Since these are placeholders, tests should just verify they return the input DataFrame. |
| 56 | +* **Test Method**: Create a sample Pandas DataFrame, pass it to these functions, and assert that the returned DataFrame is the same as the input (or an identical copy). |
| 57 | + |
| 58 | +## What to Avoid (for these basic tests) |
| 59 | + |
| 60 | +* Testing the `main()` function directly due to its complexity and heavy I/O. |
| 61 | +* Testing functions that heavily rely on external services or file system state unless very simple to set up (e.g., `read_data` or the main loop's SQLite/Databricks interaction parts). |
| 62 | +* Complex mocking of `sqlite3`, `databricks.sql`, `databricks.sdk`, or `yaml` modules. |
| 63 | + |
| 64 | +The tests should be straightforward and confirm that the core logic of these utility and argument parsing functions behaves as expected under simple conditions. |
| 65 | +When writing the tests, import the necessary functions directly from `databricks-uploader.sqlite_to_databricks_uploader`. |
0 commit comments