@@ -858,21 +858,58 @@ def setup_method(self):
858858 pr .reset ()
859859 pr .reset_settings ()
860860
861- def test_add_fact_in_bulk_with_header (self ):
862- """Test loading facts from CSV with header row."""
863- csv_content = """fact_text,name,start_time,end_time,static
864- Viewed(Zach),seen-fact-zach,0,3,False
865- Viewed(Justin),seen-fact-justin,0,3,False
866- "HaveAccess(Amy,TextMessage)",access-fact,0,5,True"""
861+ def test_add_fact_in_bulk_comprehensive (self ):
862+ """Test loading facts from CSV with various valid and invalid scenarios.
863+
864+ This test uses example_facts.csv which contains:
865+ - Valid node facts with various boolean formats
866+ - Valid edge facts with various boolean formats
867+ - Node and edge facts with interval bounds
868+ - Empty fact_text (should warn)
869+ - Invalid syntax (should warn)
870+ - Out of range intervals (should warn)
871+ - Invalid start_time (should warn)
872+ - Invalid end_time (should warn)
873+ - Invalid static value (should warn)
874+ - Empty optional fields
875+ """
876+ csv_path = 'pyreason/tests/api_tests/test_files/example_facts.csv'
877+
878+ # Expect warnings for rows with invalid data:
879+ # - Row with empty fact_text
880+ # - Row with invalid syntax (missing parentheses)
881+ # - Row with out-of-range interval values
882+ # - Row with invalid start_time
883+ # - Row with invalid end_time
884+ # - Row with invalid static value
885+ with pytest .warns (UserWarning ) as warning_list :
886+ pr .add_fact_in_bulk (csv_path )
867887
868- with tempfile .NamedTemporaryFile (mode = 'w' , suffix = '.csv' , delete = False ) as tmp :
869- tmp .write (csv_content )
870- tmp_path = tmp .name
888+ # Verify that we got warnings (at least 6 from the invalid rows)
889+ assert len (warning_list ) >= 6 , f"Expected at least 6 warnings, got { len (warning_list )} "
871890
872- try :
873- pr .add_fact_in_bulk (tmp_path )
874- finally :
875- os .unlink (tmp_path )
891+ # Check that specific warning messages appear
892+ warning_messages = [str (w .message ) for w in warning_list ]
893+
894+ # Verify warning for empty fact_text
895+ assert any ("Missing required 'fact_text'" in msg for msg in warning_messages ), \
896+ "Expected warning about missing fact_text"
897+
898+ # Verify warning for invalid syntax
899+ assert any ("Failed to parse fact" in msg and "bad-syntax" in msg for msg in warning_messages ), \
900+ "Expected warning about invalid syntax"
901+
902+ # Verify warning for invalid start_time
903+ assert any ("Invalid start_time" in msg for msg in warning_messages ), \
904+ "Expected warning about invalid start_time"
905+
906+ # Verify warning for invalid end_time
907+ assert any ("Invalid end_time" in msg for msg in warning_messages ), \
908+ "Expected warning about invalid end_time"
909+
910+ # Verify warning for invalid static value
911+ assert any ("Invalid static value" in msg for msg in warning_messages ), \
912+ "Expected warning about invalid static value"
876913
877914 def test_add_fact_in_bulk_without_header (self ):
878915 """Test loading facts from CSV without header row."""
@@ -920,8 +957,8 @@ def test_add_fact_in_bulk_empty_optional_fields(self):
920957 finally :
921958 os .unlink (tmp_path )
922959
923- def test_add_fact_in_bulk_with_invalid_facts (self ):
924- """Test that invalid facts show warnings but don't crash."""
960+ def test_add_fact_in_bulk_with_invalid_facts_warnings (self ):
961+ """Test that invalid facts produce specific warnings but don't crash."""
925962 csv_content = """fact_text,name,start_time,end_time,static
926963Viewed(Valid),valid-fact,0,3,False
927964,empty-fact-text,0,3,False
@@ -933,8 +970,18 @@ def test_add_fact_in_bulk_with_invalid_facts(self):
933970 tmp_path = tmp .name
934971
935972 try :
936- # Should not raise exception, only warnings
937- pr .add_fact_in_bulk (tmp_path )
973+ # Should produce warnings for the 3 invalid rows
974+ with pytest .warns (UserWarning ) as warning_list :
975+ pr .add_fact_in_bulk (tmp_path )
976+
977+ # Verify we got at least 3 warnings (one for each invalid row)
978+ assert len (warning_list ) >= 3 , f"Expected at least 3 warnings, got { len (warning_list )} "
979+
980+ warning_messages = [str (w .message ) for w in warning_list ]
981+
982+ # Verify specific warnings appear
983+ assert any ("Missing required 'fact_text'" in msg for msg in warning_messages )
984+ assert any ("Failed to parse fact" in msg for msg in warning_messages )
938985 finally :
939986 os .unlink (tmp_path )
940987
@@ -956,77 +1003,9 @@ def test_add_fact_in_bulk_empty_file(self):
9561003 finally :
9571004 os .unlink (tmp_path )
9581005
959- def test_add_fact_in_bulk_node_facts (self ):
960- """Test loading node facts (no commas in components)."""
961- csv_content = """fact_text,name,start_time,end_time,static
962- Viewed(Node1),fact1,0,5,False
963- Viewed(Node2),fact2,1,5,True
964- "Processed(Node3):[0.5,0.8]",fact3,0,10,False"""
965-
966- with tempfile .NamedTemporaryFile (mode = 'w' , suffix = '.csv' , delete = False ) as tmp :
967- tmp .write (csv_content )
968- tmp_path = tmp .name
969-
970- try :
971- pr .add_fact_in_bulk (tmp_path )
972- finally :
973- os .unlink (tmp_path )
974-
975- def test_add_fact_in_bulk_edge_facts (self ):
976- """Test loading edge facts (with commas, properly quoted)."""
977- csv_content = """fact_text,name,start_time,end_time,static
978- "Connected(A,B)",edge1,0,5,False
979- "Related(X,Y):True",edge2,1,5,True
980- "Knows(Person1,Person2):[0.7,0.9]",edge3,0,10,False"""
981-
982- with tempfile .NamedTemporaryFile (mode = 'w' , suffix = '.csv' , delete = False ) as tmp :
983- tmp .write (csv_content )
984- tmp_path = tmp .name
985-
986- try :
987- pr .add_fact_in_bulk (tmp_path )
988- finally :
989- os .unlink (tmp_path )
990-
991- def test_add_fact_in_bulk_mixed_fact_types (self ):
992- """Test loading both node and edge facts in same file."""
993- csv_content = """fact_text,name,start_time,end_time,static
994- Viewed(Alice),node-fact,0,3,False
995- "Connected(Alice,Bob)",edge-fact,0,3,False
996- "Processed(Charlie):[0.5,0.8]",node-interval,1,5,True
997- "Knows(X,Y):[0.3,0.7]",edge-interval,2,5,False"""
998-
999- with tempfile .NamedTemporaryFile (mode = 'w' , suffix = '.csv' , delete = False ) as tmp :
1000- tmp .write (csv_content )
1001- tmp_path = tmp .name
1002-
1003- try :
1004- pr .add_fact_in_bulk (tmp_path )
1005- finally :
1006- os .unlink (tmp_path )
1007-
1008- def test_add_fact_in_bulk_various_static_values (self ):
1009- """Test loading facts with various static value formats."""
1010- csv_content = """fact_text,name,start_time,end_time,static
1011- Viewed(A),fact1,0,5,True
1012- Viewed(B),fact2,0,5,true
1013- Viewed(C),fact3,0,5,FALSE
1014- Viewed(D),fact4,0,5,0
1015- Viewed(E),fact5,0,5,1
1016- Viewed(F),fact6,0,5,yes
1017- Viewed(G),fact7,0,5,no"""
1018-
1019- with tempfile .NamedTemporaryFile (mode = 'w' , suffix = '.csv' , delete = False ) as tmp :
1020- tmp .write (csv_content )
1021- tmp_path = tmp .name
1022-
1023- try :
1024- pr .add_fact_in_bulk (tmp_path )
1025- finally :
1026- os .unlink (tmp_path )
10271006
10281007 def test_add_fact_in_bulk_invalid_start_end_times (self ):
1029- """Test loading facts with invalid start/end time values."""
1008+ """Test loading facts with invalid start/end time values produce warnings ."""
10301009 csv_content = """fact_text,name,start_time,end_time,static
10311010Viewed(A),fact1,abc,5,False
10321011Viewed(B),fact2,0,xyz,False"""
@@ -1037,7 +1016,19 @@ def test_add_fact_in_bulk_invalid_start_end_times(self):
10371016
10381017 try :
10391018 # Should load facts with warnings about invalid times (using defaults)
1040- pr .add_fact_in_bulk (tmp_path )
1019+ with pytest .warns (UserWarning ) as warning_list :
1020+ pr .add_fact_in_bulk (tmp_path )
1021+
1022+ # Verify we got warnings for both invalid time values
1023+ assert len (warning_list ) >= 2 , f"Expected at least 2 warnings, got { len (warning_list )} "
1024+
1025+ warning_messages = [str (w .message ) for w in warning_list ]
1026+
1027+ # Verify specific warnings appear
1028+ assert any ("Invalid start_time" in msg for msg in warning_messages ), \
1029+ "Expected warning about invalid start_time"
1030+ assert any ("Invalid end_time" in msg for msg in warning_messages ), \
1031+ "Expected warning about invalid end_time"
10411032 finally :
10421033 os .unlink (tmp_path )
10431034
@@ -1061,21 +1052,6 @@ def test_add_fact_in_bulk_multiple_calls(self):
10611052 os .unlink (tmp1_path )
10621053 os .unlink (tmp2_path )
10631054
1064- def test_add_fact_in_bulk_example_file_with_header (self ):
1065- """Test loading facts from example CSV file with header."""
1066- csv_path = 'tests/api_tests/test_files/example_facts.csv'
1067-
1068- # Only run if example file exists
1069- if os .path .exists (csv_path ):
1070- pr .add_fact_in_bulk (csv_path )
1071-
1072- def test_add_fact_in_bulk_example_file_without_header (self ):
1073- """Test loading facts from example CSV file without header."""
1074- csv_path = 'tests/api_tests/test_files/example_facts_no_header.csv'
1075-
1076- # Only run if example file exists
1077- if os .path .exists (csv_path ):
1078- pr .add_fact_in_bulk (csv_path )
10791055
10801056
10811057class TestRuleTrace :
0 commit comments