Skip to content

Commit 168aabe

Browse files
committed
Add several tests for _process_data()
1 parent cd1b9c4 commit 168aabe

1 file changed

Lines changed: 260 additions & 0 deletions

File tree

tests/test_validate.py

Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
_process_brief,
5151
_process_connection_string,
5252
_process_csv_input,
53+
_process_data,
5354
_process_parquet_input,
5455
connect_to_table,
5556
_process_title_text,
@@ -7801,6 +7802,265 @@ def test_process_action_str():
78017802
)
78027803

78037804

7805+
def test_process_data_dataframe_passthrough_polars():
7806+
pl = pytest.importorskip("polars")
7807+
7808+
# Create test DataFrame
7809+
df = pl.DataFrame({"a": [1, 2, 3], "b": ["x", "y", "z"]})
7810+
7811+
# Process through the function
7812+
result = _process_data(df)
7813+
7814+
# Should be the same object
7815+
assert result is df
7816+
7817+
7818+
def test_process_data_dataframe_passthrough_pandas():
7819+
pd = pytest.importorskip("pandas")
7820+
7821+
# Create test DataFrame
7822+
df = pd.DataFrame({"a": [1, 2, 3], "b": ["x", "y", "z"]})
7823+
7824+
# Process through the function
7825+
result = _process_data(df)
7826+
7827+
# Should be the same object
7828+
assert result is df
7829+
7830+
7831+
def test_process_data_non_data_passthrough():
7832+
test_cases = [
7833+
42, # Integer
7834+
3.14, # Float
7835+
"not_a_file.txt", # Random string
7836+
["list", "of", "items"], # List
7837+
{"key": "value"}, # Dict
7838+
None, # None
7839+
]
7840+
7841+
for test_input in test_cases:
7842+
result = _process_data(test_input)
7843+
assert result is test_input
7844+
7845+
7846+
def test_process_data_csv_file_processing():
7847+
pl = pytest.importorskip("polars")
7848+
7849+
# Create test DataFrame and temporary CSV file
7850+
df = pl.DataFrame({"a": [1, 2, 3], "b": ["x", "y", "z"], "c": [1.1, 2.2, 3.3]})
7851+
7852+
with tempfile.NamedTemporaryFile(mode="w", suffix=".csv", delete=False) as f:
7853+
df.write_csv(f.name)
7854+
csv_path = f.name
7855+
7856+
try:
7857+
# Process the CSV file
7858+
result = _process_data(csv_path)
7859+
7860+
# Should return a DataFrame
7861+
assert hasattr(result, "columns") or hasattr(result, "shape")
7862+
assert len(result) == 3 # Should have 3 rows
7863+
7864+
finally:
7865+
# Clean up
7866+
Path(csv_path).unlink()
7867+
7868+
7869+
def test_process_data_csv_path_object_processing():
7870+
pl = pytest.importorskip("polars")
7871+
7872+
# Create test DataFrame and temporary CSV file
7873+
df = pl.DataFrame({"a": [1, 2, 3], "b": ["x", "y", "z"], "c": [1.1, 2.2, 3.3]})
7874+
7875+
with tempfile.NamedTemporaryFile(mode="w", suffix=".csv", delete=False) as f:
7876+
df.write_csv(f.name)
7877+
path_obj = Path(f.name)
7878+
7879+
try:
7880+
# Process the Path object
7881+
result = _process_data(path_obj)
7882+
7883+
# Should return a DataFrame
7884+
assert hasattr(result, "columns") or hasattr(result, "shape")
7885+
assert len(result) == 3 # Should have 3 rows
7886+
7887+
finally:
7888+
# Clean up
7889+
path_obj.unlink()
7890+
7891+
7892+
def test_process_data_parquet_file_processing():
7893+
pl = pytest.importorskip("polars")
7894+
7895+
# Create test DataFrame and temporary Parquet file
7896+
df = pl.DataFrame({"x": [10, 20, 30], "y": ["a", "b", "c"], "z": [10.5, 20.5, 30.5]})
7897+
7898+
with tempfile.NamedTemporaryFile(mode="w", suffix=".parquet", delete=False) as f:
7899+
df.write_parquet(f.name)
7900+
parquet_path = f.name
7901+
7902+
try:
7903+
# Process the Parquet file
7904+
result = _process_data(parquet_path)
7905+
7906+
# Should return a DataFrame
7907+
assert hasattr(result, "columns") or hasattr(result, "shape")
7908+
assert len(result) == 3 # Should have 3 rows
7909+
7910+
finally:
7911+
# Clean up
7912+
Path(parquet_path).unlink()
7913+
7914+
7915+
def test_process_data_nonexistent_file():
7916+
# Test CSV
7917+
with pytest.raises(FileNotFoundError):
7918+
_process_data("nonexistent_file.csv")
7919+
7920+
# Test Parquet
7921+
with pytest.raises(FileNotFoundError):
7922+
_process_data("nonexistent_file.parquet")
7923+
7924+
7925+
def test_process_data_processing_order():
7926+
# This test ensures GitHub URLs are processed before connection strings
7927+
# by mocking the individual processing functions
7928+
7929+
test_input = "test_string"
7930+
7931+
with (
7932+
patch("pointblank.validate._process_github_url") as mock_github,
7933+
patch("pointblank.validate._process_connection_string") as mock_conn,
7934+
patch("pointblank.validate._process_csv_input") as mock_csv,
7935+
patch("pointblank.validate._process_parquet_input") as mock_parquet,
7936+
):
7937+
# Set up the mocks to pass through the input
7938+
mock_github.return_value = test_input
7939+
mock_conn.return_value = test_input
7940+
mock_csv.return_value = test_input
7941+
mock_parquet.return_value = test_input
7942+
7943+
# Call the function
7944+
result = _process_data(test_input)
7945+
7946+
# Verify the order of calls
7947+
mock_github.assert_called_once_with(test_input)
7948+
mock_conn.assert_called_once_with(test_input)
7949+
mock_csv.assert_called_once_with(test_input)
7950+
mock_parquet.assert_called_once_with(test_input)
7951+
7952+
# Verify result
7953+
assert result == test_input
7954+
7955+
7956+
@patch("pointblank.validate._process_github_url")
7957+
def test_process_data_github_url_processing(mock_github):
7958+
pl = pytest.importorskip("polars")
7959+
7960+
# Mock the GitHub processing to return a DataFrame
7961+
mock_df = pl.DataFrame({"test": [1, 2, 3]})
7962+
mock_github.return_value = mock_df
7963+
7964+
# Test with a GitHub URL
7965+
github_url = "https://github.com/user/repo/blob/main/data.csv"
7966+
result = _process_data(github_url)
7967+
7968+
# Verify GitHub processing was called
7969+
mock_github.assert_called_once_with(github_url)
7970+
assert result is mock_df
7971+
7972+
7973+
def test_process_data_case_insensitive_extensions():
7974+
pl = pytest.importorskip("polars")
7975+
7976+
# Create test DataFrame
7977+
df = pl.DataFrame({"test": [1, 2, 3]})
7978+
7979+
# Test CSV with uppercase extension
7980+
with tempfile.NamedTemporaryFile(mode="w", suffix=".CSV", delete=False) as f:
7981+
df.write_csv(f.name)
7982+
csv_path = f.name
7983+
7984+
try:
7985+
result = _process_data(csv_path)
7986+
assert hasattr(result, "columns") or hasattr(result, "shape")
7987+
finally:
7988+
Path(csv_path).unlink()
7989+
7990+
7991+
def test_process_data_integration_with_validate_class():
7992+
pl = pytest.importorskip("polars")
7993+
7994+
# Create test DataFrame and temporary CSV file
7995+
df = pl.DataFrame({"a": [1, 2, 3], "b": ["x", "y", "z"], "c": [1.1, 2.2, 3.3]})
7996+
7997+
with tempfile.NamedTemporaryFile(mode="w", suffix=".csv", delete=False) as f:
7998+
df.write_csv(f.name)
7999+
csv_path = f.name
8000+
8001+
try:
8002+
# Create a Validate instance with CSV path
8003+
validation = Validate(data=csv_path)
8004+
8005+
# The data should have been processed into a DataFrame
8006+
assert hasattr(validation.data, "columns") or hasattr(validation.data, "shape")
8007+
assert len(validation.data) == 3
8008+
8009+
finally:
8010+
# Clean up
8011+
Path(csv_path).unlink()
8012+
8013+
8014+
def test_process_data_error_handling():
8015+
# Test with invalid file paths
8016+
with pytest.raises((FileNotFoundError, OSError)):
8017+
_process_data("/invalid/path/file.csv")
8018+
8019+
8020+
def test_process_data_with_connection_string():
8021+
with patch("pointblank.validate._process_connection_string") as mock_conn:
8022+
mock_table = Mock()
8023+
mock_conn.return_value = mock_table
8024+
8025+
# Test that the function delegates to connection string processing
8026+
result = _process_data("duckdb://test.db::table")
8027+
8028+
# Should call _process_connection_string and return the result
8029+
mock_conn.assert_called_once_with("duckdb://test.db::table")
8030+
assert result == mock_table
8031+
8032+
8033+
def test_process_data_dataframe_goes_through_pipeline():
8034+
pl = pytest.importorskip("polars")
8035+
8036+
# Create test DataFrame
8037+
df = pl.DataFrame({"test": [1, 2, 3]})
8038+
8039+
with (
8040+
patch("pointblank.validate._process_github_url") as mock_github,
8041+
patch("pointblank.validate._process_connection_string") as mock_conn,
8042+
patch("pointblank.validate._process_csv_input") as mock_csv,
8043+
patch("pointblank.validate._process_parquet_input") as mock_parquet,
8044+
):
8045+
# Set up the mocks to pass through the input (as they would for DataFrames)
8046+
mock_github.return_value = df
8047+
mock_conn.return_value = df
8048+
mock_csv.return_value = df
8049+
mock_parquet.return_value = df
8050+
8051+
# Call the function with a DataFrame
8052+
result = _process_data(df)
8053+
8054+
# Should return the DataFrame after going through all processing functions
8055+
assert result is df
8056+
8057+
# All processing functions should have been called
8058+
mock_github.assert_called_once_with(df)
8059+
mock_conn.assert_called_once_with(df)
8060+
mock_csv.assert_called_once_with(df)
8061+
mock_parquet.assert_called_once_with(df)
8062+
8063+
78048064
def test_process_title_text():
78058065
assert _process_title_text(title=None, tbl_name=None, lang="en") == ""
78068066
assert (

0 commit comments

Comments
 (0)