mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 10:42:05 +03:00
Make Table.should_equal and Column.should_equal consider NaN equal (#9799)
* Make Column.should_equal detect colums of different types and think nan==nan * Refactor Table.should_equal * More Column tests * Adjust spacing * Tests Green * Check same number of columns * Refactor * Extra test * Code Review Changes * Fix * Fix * Fix tests * Fix Tests * Fix Test * Fix test * Code review change
This commit is contained in:
parent
04a10b72e5
commit
32c3f5f3e8
@ -6,6 +6,7 @@ import java.time.LocalTime;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
import org.enso.base.polyglot.NumericConverter;
|
||||
import org.enso.base.polyglot.Polyglot_Utils;
|
||||
import org.enso.table.data.column.storage.Storage;
|
||||
import org.enso.table.data.column.storage.type.BigIntegerType;
|
||||
import org.enso.table.data.column.storage.type.BooleanType;
|
||||
@ -61,6 +62,9 @@ public class InferredBuilder extends Builder {
|
||||
|
||||
@Override
|
||||
public void append(Object o) {
|
||||
// ToDo: This a workaround for an issue with polyglot layer. #5590 is related.
|
||||
o = Polyglot_Utils.convertPolyglotValue(o);
|
||||
|
||||
if (currentBuilder == null) {
|
||||
if (o == null) {
|
||||
currentSize++;
|
||||
|
@ -298,7 +298,7 @@ add_specs suite_builder =
|
||||
suite_builder.group "Edge cases" group_builder->
|
||||
group_builder.specify "empty table is ok" <|
|
||||
input = Column.from_vector "values" [Date.new 2020 12 21, Date.new 2023 4 25] . take 0
|
||||
expected = Column.from_vector "values" []
|
||||
expected = Column.from_vector "values" [""] . take 0
|
||||
actual = input.format "yyyyMMdd"
|
||||
actual . should_equal expected
|
||||
|
||||
|
@ -351,7 +351,7 @@ add_specs suite_builder =
|
||||
|
||||
group_builder.specify "empty table" <|
|
||||
t = Table.from_rows ["foo", "bar", "baz"] [["x", "a", "y"]] . take 0
|
||||
expected = Table.from_rows ["foo", "bar", "baz"] []
|
||||
expected = Table.from_rows ["foo", "bar", "baz"] [["x", "a", "y"]] . take 0
|
||||
actual = t.parse_to_columns "bar" "\d+"
|
||||
actual.should_equal expected
|
||||
|
||||
@ -380,13 +380,13 @@ add_specs suite_builder =
|
||||
|
||||
group_builder.specify "input with no matches, with regex groups" <|
|
||||
t = Table.from_rows ["foo", "bar", "baz"] [["x", "a", "y"]]
|
||||
expected = Table.from_rows ["foo", "bar 1", "bar 2", "baz"] [["x", Nothing, Nothing, "y"]]
|
||||
expected = Table.from_rows ["foo", "bar 1", "bar 2", "baz"] [["x", Nothing, Nothing, "y"], ["", "", "", ""]] . take 1
|
||||
actual = t.parse_to_columns "bar" "(\d)(\d)"
|
||||
actual.should_equal expected
|
||||
|
||||
group_builder.specify "input with no matches, with named and unnamed regex groups" <|
|
||||
t = Table.from_rows ["foo", "bar", "baz"] [["x", "a", "y"]]
|
||||
expected = Table.from_rows ["foo", "quux", "bar 1", "foo 1", "bar 2", "baz"] [["x", Nothing, Nothing, Nothing, Nothing, "y"]]
|
||||
expected = Table.from_rows ["foo", "quux", "bar 1", "foo 1", "bar 2", "baz"] [["x", Nothing, Nothing, Nothing, Nothing, "y"], ["", "", "", "", "", ""]] . take 1
|
||||
actual = t.parse_to_columns "bar" "(?<quux>)(\d)(?<foo>\d)(\d)"
|
||||
actual.should_equal expected
|
||||
|
||||
|
@ -7,6 +7,7 @@ import project.Formatting
|
||||
import project.Helpers
|
||||
import project.In_Memory
|
||||
import project.IO
|
||||
import project.Util_Spec
|
||||
|
||||
main filter=Nothing =
|
||||
suite = Test.build suite_builder->
|
||||
@ -15,5 +16,6 @@ main filter=Nothing =
|
||||
Formatting.Main.add_specs suite_builder
|
||||
Database.Main.add_specs suite_builder
|
||||
Helpers.Main.add_specs suite_builder
|
||||
Util_Spec.add_specs suite_builder
|
||||
|
||||
suite.run_with_filter filter
|
||||
|
@ -11,29 +11,14 @@ polyglot java import org.enso.base_test_helpers.FileSystemHelper
|
||||
Table.should_equal : Any -> Integer -> Any
|
||||
Table.should_equal self expected frames_to_skip=0 =
|
||||
loc = Meta.get_source_location 1+frames_to_skip
|
||||
case expected of
|
||||
_ : Table ->
|
||||
tables_equal t0 t1 =
|
||||
same_headers = (t0.columns.map .name) == (t1.columns.map .name)
|
||||
same_columns = (t0.columns.map .to_vector) == (t1.columns.map .to_vector)
|
||||
same_headers && same_columns
|
||||
equal = tables_equal self expected
|
||||
if equal.not then
|
||||
msg = 'Tables differ at '+loc+'.\nActual:\n' + self.display + '\nExpected:\n' + expected.display
|
||||
Test.fail msg
|
||||
_ -> Test.fail "Got a Table, but expected a "+expected.to_display_text+' (at '+loc+').'
|
||||
Panic.catch Test_Failure_Error (table_should_equal_impl self expected loc) error->
|
||||
Test.fail error.payload.message
|
||||
|
||||
Column.should_equal : Any -> Integer -> Any
|
||||
Column.should_equal self expected frames_to_skip=0 =
|
||||
loc = Meta.get_source_location 1+frames_to_skip
|
||||
case expected of
|
||||
_ : Column ->
|
||||
if self.name != expected.name then
|
||||
Test.fail "Expected column name "+expected.name+", but got "+self.name+" (at "+loc+")."
|
||||
if self.length != expected.length then
|
||||
Test.fail "Expected column length "+expected.length.to_text+", but got "+self.length.to_text+" (at "+loc+")."
|
||||
self.to_vector.should_equal expected.to_vector 2+frames_to_skip
|
||||
_ -> Test.fail "Got a Column, but expected a "+expected.to_display_text+' (at '+loc+').'
|
||||
Panic.catch Test_Failure_Error (column_should_equal_impl self expected loc) error->
|
||||
Test.fail error.payload.message
|
||||
|
||||
DB_Table.should_equal : DB_Table -> Integer -> Any
|
||||
DB_Table.should_equal self expected frames_to_skip=0 =
|
||||
@ -47,6 +32,60 @@ DB_Column.should_equal self expected frames_to_skip=0 =
|
||||
t1 = expected.read
|
||||
t0 . should_equal t1 frames_to_skip
|
||||
|
||||
type Test_Failure_Error
|
||||
## PRIVATE
|
||||
The runtime representation of a test failure.
|
||||
|
||||
Arguments:
|
||||
- message: A description of the test failure.
|
||||
Error message
|
||||
|
||||
## PRIVATE
|
||||
to_display_text : Text
|
||||
to_display_text self = "Test failure error: "+self.message
|
||||
|
||||
## PRIVATE
|
||||
table_should_equal_impl actual expected loc =
|
||||
case expected of
|
||||
_ : Table ->
|
||||
if actual.columns.length != expected.columns.length then
|
||||
Panic.throw (Test_Failure_Error.Error 'Tables differ at '+loc+'.\nActual:\n'+actual.display+'\nExpected:\n'+expected.display+'\nExpected '+expected.columns.length.to_text+" columns, but got "+actual.columns.length.to_text+'.')
|
||||
Panic.catch Test_Failure_Error (actual.columns.zip expected.columns a-> e->(column_should_equal_impl a e)) error->
|
||||
msg = 'Tables differ at '+loc+'.\nActual:\n'+actual.display+'\nExpected:\n'+expected.display+'\n'+error.payload.message
|
||||
Panic.throw (Test_Failure_Error.Error msg)
|
||||
_ -> Panic.throw (Test_Failure_Error.Error "Got a Table, but expected a "+expected.to_display_text+(display_loc loc)+'.')
|
||||
|
||||
## PRIVATE
|
||||
column_should_equal_impl actual expected loc='' =
|
||||
case expected of
|
||||
_ : Column ->
|
||||
if actual.name != expected.name then
|
||||
Panic.throw (Test_Failure_Error.Error "Expected column name "+expected.name+", but got "+actual.name+(display_loc loc)+'.')
|
||||
if actual.length != expected.length then
|
||||
Panic.throw (Test_Failure_Error.Error "Expected column length "+expected.length.to_text+", but got "+actual.length.to_text+(display_loc loc)+'.')
|
||||
if actual.value_type != expected.value_type then
|
||||
Panic.throw (Test_Failure_Error.Error "Expected column type "+expected.value_type.to_text+", but got "+actual.value_type.to_text+(display_loc loc)+'.')
|
||||
actual.zip expected a-> e->
|
||||
if values_equal a e then
|
||||
report_fail actual expected loc
|
||||
_ -> Panic.throw (Test_Failure_Error.Error "Got a Column, but expected a "+expected.to_display_text+(display_loc loc)+'.')
|
||||
|
||||
## PRIVATE
|
||||
values_equal a e =
|
||||
a != e && (a.is_a Number && e.is_a Number && a.is_nan && e.is_nan).not
|
||||
|
||||
## PRIVATE
|
||||
report_fail actual expected loc =
|
||||
indexed = actual.zip (0.up_to actual.length) a-> i-> Pair.new a i
|
||||
indexed.zip expected a-> e->
|
||||
if values_equal a.first e then
|
||||
Panic.throw (Test_Failure_Error.Error "Column: "+actual.name+" differs at row "+a.second.to_text+'.\n\t Actual : '+a.first.to_text+'\n\t Expected: '+e.to_text+'\n\t'+(display_loc loc)+'.')
|
||||
|
||||
## PRIVATE
|
||||
display_loc loc:Text =
|
||||
if loc.is_empty then '' else
|
||||
' (at '+loc+')'
|
||||
|
||||
normalize_lines string line_separator=Line_Ending_Style.Unix.to_text newline_at_end=True =
|
||||
case newline_at_end of
|
||||
True -> string.lines.join line_separator suffix=line_separator
|
||||
|
81
test/Table_Tests/src/Util_Spec.enso
Normal file
81
test/Table_Tests/src/Util_Spec.enso
Normal file
@ -0,0 +1,81 @@
|
||||
from Standard.Base import all
|
||||
from Standard.Table import Column, Table
|
||||
from project.Util import all
|
||||
from Standard.Test import all
|
||||
|
||||
add_specs suite_builder =
|
||||
suite_builder.group "Column should_equal" group_builder->
|
||||
group_builder.specify "Two Columns Are Equal" <|
|
||||
expected_column = Column.from_vector "Col" ["Quis", "custodiet", "ipsos", "custodes?"]
|
||||
actual_column = Column.from_vector "Col" ["Quis", "custodiet", "ipsos", "custodes?"]
|
||||
actual_column.should_equal expected_column
|
||||
group_builder.specify "Two Columns With Different Name are Not Equal" <|
|
||||
expected_column = Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"]
|
||||
actual_column = Column.from_vector "Col2" ["Quis", "custodiet", "ipsos", "custodes?"]
|
||||
res = Panic.recover Test_Failure_Error (column_should_equal_impl actual_column expected_column "LOCATION_PATH")
|
||||
res.catch.message.should_equal "Expected column name Col1, but got Col2 (at LOCATION_PATH)."
|
||||
group_builder.specify "Two Columns With Different Lengths are Not Equal" <|
|
||||
expected_column = Column.from_vector "Col" ["Quis", "custodiet", "ipsos", "custodes?"]
|
||||
actual_column = Column.from_vector "Col" ["Quis", "custodiet", "ipsos"]
|
||||
res = Panic.recover Test_Failure_Error (column_should_equal_impl actual_column expected_column "LOCATION_PATH")
|
||||
res.catch.message.should_equal "Expected column length 4, but got 3 (at LOCATION_PATH)."
|
||||
group_builder.specify "Two Columns with different content Are Not Equal" <|
|
||||
expected_column = Column.from_vector "Col" ["Quis", "custodiet", "ipsos", "custodes?"]
|
||||
actual_column = Column.from_vector "Col" ["Who", "guards", "the", "guards?"]
|
||||
res = Panic.recover Test_Failure_Error (column_should_equal_impl actual_column expected_column "LOCATION_PATH")
|
||||
res.catch.message.should_equal 'Column: Col differs at row 0.\n\t Actual : Who\n\t Expected: Quis\n\t (at LOCATION_PATH).'
|
||||
group_builder.specify "Two Columns Are Not Equal in Row 3" <|
|
||||
expected_column = Column.from_vector "My Column" ["Quis", "custodiet", "ipsos", "custodes?"]
|
||||
actual_column = Column.from_vector "My Column" ["Quis", "custodiet", "ipsos", "guards?"]
|
||||
res = Panic.recover Test_Failure_Error (column_should_equal_impl actual_column expected_column "LOCATION_PATH")
|
||||
res.catch.message.should_equal 'Column: My Column differs at row 3.\n\t Actual : guards?\n\t Expected: custodes?\n\t (at LOCATION_PATH).'
|
||||
group_builder.specify "Two Columns with different types Are Not Equal" <|
|
||||
expected_column = Column.from_vector "Col" ["1", "2", "3", "4"]
|
||||
actual_column = Column.from_vector "Col" [1, 2, 3, 4]
|
||||
res = Panic.recover Test_Failure_Error (column_should_equal_impl actual_column expected_column "LOCATION_PATH")
|
||||
res.catch.message.should_equal "Expected column type (Char Nothing True), but got (Integer 64 bits) (at LOCATION_PATH)."
|
||||
group_builder.specify "Comparing a Column to non column" <|
|
||||
expected_column = 42
|
||||
actual_column = Column.from_vector "Col" [1, 2, 3, 4]
|
||||
res = Panic.recover Test_Failure_Error (column_should_equal_impl actual_column expected_column "LOCATION_PATH")
|
||||
res.catch.message.should_equal "Got a Column, but expected a 42 (at LOCATION_PATH)."
|
||||
group_builder.specify "Two Columns Containg NaNs Are Equal" <|
|
||||
# This is somewhat of a special case, as NaN != NaN but for the purposes of testing we consider them equal
|
||||
expected_column = Column.from_vector "Col" [1.0, 2.0, Number.nan]
|
||||
actual_column = Column.from_vector "Col" [1.0, 2.0, Number.nan]
|
||||
actual_column.should_equal expected_column
|
||||
suite_builder.group "Table should_equal" group_builder->
|
||||
group_builder.specify "Two Tables Are Equal" <|
|
||||
expected_table = Table.new [Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"], Column.from_vector "Col2" ["Who", "guards", "the", "guards?"]]
|
||||
actual_table = Table.new [Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"], Column.from_vector "Col2" ["Who", "guards", "the", "guards?"]]
|
||||
actual_table.should_equal expected_table
|
||||
group_builder.specify "Two Tables With Different Values" <|
|
||||
expected_table = Table.new [Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"], Column.from_vector "Col2" ["Who", "guards", "the", "guards?"]]
|
||||
actual_table = Table.new [Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"], Column.from_vector "Col2" ["Who", "guards", "teh", "guards?"]]
|
||||
res = Panic.recover Test_Failure_Error (table_should_equal_impl actual_table expected_table "LOCATION_PATH")
|
||||
res.catch.message.should_end_with 'Column: Col2 differs at row 2.\n\t Actual : teh\n\t Expected: the\n\t.'
|
||||
group_builder.specify "Tables different number of columns" <|
|
||||
expected_table = Table.new [Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"]]
|
||||
actual_table = Table.new [Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"], Column.from_vector "Col2" ["Who", "guards", "the", "guards?"]]
|
||||
res = Panic.recover Test_Failure_Error (table_should_equal_impl actual_table expected_table "LOCATION_PATH")
|
||||
res.catch.message.should_end_with "Expected 1 columns, but got 2."
|
||||
group_builder.specify "Tables different number of columns2" <|
|
||||
expected_table = Table.new [Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"], Column.from_vector "Col2" ["Who", "guards", "the", "guards?"]]
|
||||
actual_table = Table.new [Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"]]
|
||||
res = Panic.recover Test_Failure_Error (table_should_equal_impl actual_table expected_table "LOCATION_PATH")
|
||||
res.catch.message.should_end_with "Expected 2 columns, but got 1."
|
||||
group_builder.specify "Tables With Mismatched Column names" <|
|
||||
expected_table = Table.new [Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"], Column.from_vector "Col2" ["Who", "guards", "the", "guards?"]]
|
||||
actual_table = Table.new [Column.from_vector "Col" ["Quis", "custodiet", "ipsos", "custodes?"], Column.from_vector "Col2" ["Who", "guards", "the", "guards?"]]
|
||||
res = Panic.recover Test_Failure_Error (table_should_equal_impl actual_table expected_table "LOCATION_PATH")
|
||||
res.catch.message.should_end_with "Expected column name Col1, but got Col."
|
||||
group_builder.specify "Comparing a Table to non Table" <|
|
||||
expected_table = 42
|
||||
actual_table = Table.new [Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"]]
|
||||
res = Panic.recover Test_Failure_Error (table_should_equal_impl actual_table expected_table "LOCATION_PATH")
|
||||
res.catch.message.should_equal "Got a Table, but expected a 42 (at LOCATION_PATH)."
|
||||
|
||||
main filter=Nothing =
|
||||
suite = Test.build suite_builder->
|
||||
add_specs suite_builder
|
||||
suite.run_with_filter filter
|
Loading…
Reference in New Issue
Block a user