import pandas as pd from app.features import FEATURE_COLUMNS, engineer_features def _raw_frame() -> pd.DataFrame: return pd.DataFrame( [ # step, type, amount, nameOrig, oldOrig, newOrig, nameDest, oldDest, newDest [1, "TRANSFER", 100.0, "C1", 100.0, 0.0, "C2", 0.0, 0.0], [2, "PAYMENT", 50.0, "C1", 0.0, 0.0, "M1", 0.0, 0.0], [3, "CASH_OUT", 200.0, "C3", 500.0, 300.0, "C2", 1000.0, 1200.0], ], columns=[ "step", "type", "amount", "nameOrig", "oldbalanceOrg", "newbalanceOrig", "nameDest", "oldbalanceDest", "newbalanceDest", ], ) def test_engineer_features_adds_all_feature_columns(): out = engineer_features(_raw_frame()) for col in FEATURE_COLUMNS: assert col in out.columns def test_type_one_hot_is_mutually_exclusive(): out = engineer_features(_raw_frame()) type_cols = [c for c in out.columns if c.startswith("type_")] assert (out[type_cols].sum(axis=1) == 1).all() def test_orig_zero_after_flag_detects_fraud_like_pattern(): out = engineer_features(_raw_frame()) row = out[out["nameOrig"] == "C1"].iloc[0] assert row["orig_zero_after_flag"] == 1 def test_dest_is_merchant_flag(): out = engineer_features(_raw_frame()) row = out[out["nameDest"] == "M1"].iloc[0] assert row["dest_is_merchant"] == 1 row2 = out[out["nameDest"] == "C2"].iloc[0] assert row2["dest_is_merchant"] == 0 def test_velocity_only_counts_prior_transactions(): df = pd.DataFrame( [ [1, "PAYMENT", 10.0, "C1", 100.0, 90.0, "M1", 0.0, 0.0], [2, "PAYMENT", 10.0, "C1", 90.0, 80.0, "M1", 0.0, 0.0], [3, "PAYMENT", 10.0, "C1", 80.0, 70.0, "M1", 0.0, 0.0], ], columns=[ "step", "type", "amount", "nameOrig", "oldbalanceOrg", "newbalanceOrig", "nameDest", "oldbalanceDest", "newbalanceDest", ], ) out = engineer_features(df) counts = out.sort_values("step")["orig_prior_txn_count"].tolist() assert counts == [0, 1, 2] def test_balance_consistency_flags_true_when_arithmetic_matches(): df = pd.DataFrame( [[1, "CASH_OUT", 100.0, "C1", 500.0, 400.0, "C2", 200.0, 300.0]], columns=[ "step", "type", "amount", "nameOrig", "oldbalanceOrg", "newbalanceOrig", "nameDest", "oldbalanceDest", "newbalanceDest", ], ) out = engineer_features(df) assert out.iloc[0]["orig_balance_consistent"] == 1 assert out.iloc[0]["dest_balance_consistent"] == 1