77import warnings
88
99from RAT .classlist import ClassList
10- from tests .utils import InputAttributes
10+ from tests .utils import InputAttributes , SubInputAttributes
1111
1212
1313@pytest .fixture
@@ -59,7 +59,21 @@ def test_input_sequence(self, input_sequence: Sequence[object]) -> None:
5959 """
6060 class_list = ClassList (input_sequence )
6161 assert class_list .data == list (input_sequence )
62- assert isinstance (input_sequence [- 1 ], class_list ._class_handle )
62+ for element in input_sequence :
63+ assert isinstance (element , class_list ._class_handle )
64+
65+ @pytest .mark .parametrize ("input_sequence" , [
66+ ([InputAttributes (name = 'Alice' ), SubInputAttributes (name = 'Bob' )]),
67+ ([SubInputAttributes (name = 'Alice' ), InputAttributes (name = 'Bob' )]),
68+ ])
69+ def test_input_sequence_subclass (self , input_sequence : Sequence [object ]) -> None :
70+ """For an input of a sequence containing objects of a class and its subclasses, the ClassList should be a list
71+ equal to the input sequence, and _class_handle should be set to the type of the parent class.
72+ """
73+ class_list = ClassList (input_sequence )
74+ assert class_list .data == list (input_sequence )
75+ for element in input_sequence :
76+ assert isinstance (element , class_list ._class_handle )
6377
6478 @pytest .mark .parametrize ("empty_input" , [([]), (())])
6579 def test_empty_input (self , empty_input : Sequence [object ]) -> None :
@@ -119,26 +133,33 @@ def test_repr_empty_classlist() -> None:
119133 assert repr (ClassList ()) == repr ([])
120134
121135
122- @pytest .mark .parametrize (["new_values " , "expected_classlist" ], [
123- ({ ' name' : ' Eve'} , ClassList ([InputAttributes (name = 'Eve' ), InputAttributes (name = 'Bob' )])),
124- ({ ' name' : ' John' , ' surname' : ' Luther'} ,
136+ @pytest .mark .parametrize (["new_item " , "expected_classlist" ], [
137+ (InputAttributes ( name = ' Eve') , ClassList ([InputAttributes (name = 'Eve' ), InputAttributes (name = 'Bob' )])),
138+ (InputAttributes ( name = ' John' , surname = ' Luther') ,
125139 ClassList ([InputAttributes (name = 'John' , surname = 'Luther' ), InputAttributes (name = 'Bob' )])),
126140])
127- def test_setitem (two_name_class_list : ' ClassList' , new_values : dict [ str , Any ], expected_classlist : ' ClassList' ) -> None :
128- """We should be able to set values in an element of a ClassList using a dictionary ."""
141+ def test_setitem (two_name_class_list : ClassList , new_item : InputAttributes , expected_classlist : ClassList ) -> None :
142+ """We should be able to set values in an element of a ClassList using a new object ."""
129143 class_list = two_name_class_list
130- class_list [0 ] = new_values
144+ class_list [0 ] = new_item
131145 assert class_list == expected_classlist
132146
133147
148+ @pytest .mark .parametrize ("new_item" , [
149+ (InputAttributes (name = 'Bob' )),
150+ ])
151+ def test_setitem_same_name_field (two_name_class_list : 'ClassList' , new_item : InputAttributes ) -> None :
152+ """If we set the name_field of an object in the ClassList to one already defined, we should raise a ValueError."""
153+ with pytest .raises (ValueError , match = "Input list contains objects with the same value of the name attribute" ):
154+ two_name_class_list [0 ] = new_item
155+
156+
134157@pytest .mark .parametrize ("new_values" , [
135- ({ 'name' : ' Bob'}) ,
158+ ' Bob' ,
136159])
137- def test_setitem_same_name_field (two_name_class_list : 'ClassList' , new_values : dict [str , Any ]) -> None :
160+ def test_setitem_different_classes (two_name_class_list : 'ClassList' , new_values : dict [str , Any ]) -> None :
138161 """If we set the name_field of an object in the ClassList to one already defined, we should raise a ValueError."""
139- with pytest .raises (ValueError , match = f"Input arguments contain the { two_name_class_list .name_field } "
140- f"'{ new_values [two_name_class_list .name_field ]} ', "
141- f"which is already specified in the ClassList" ):
162+ with pytest .raises (ValueError , match = f"Input list contains elements of type other than 'InputAttributes'" ):
142163 two_name_class_list [0 ] = new_values
143164
144165
@@ -160,9 +181,11 @@ def test_delitem_not_present(two_name_class_list: 'ClassList') -> None:
160181 (ClassList (InputAttributes (name = 'Eve' ))),
161182 ([InputAttributes (name = 'Eve' )]),
162183 (InputAttributes (name = 'Eve' ),),
184+ (InputAttributes (name = 'Eve' )),
163185])
164186def test_iadd (two_name_class_list : 'ClassList' , added_list : Iterable , three_name_class_list : 'ClassList' ) -> None :
165- """We should be able to use the "+=" operator to add iterables to a ClassList."""
187+ """We should be able to use the "+=" operator to add iterables to a ClassList. Individual objects should be wrapped
188+ in a list before being added."""
166189 class_list = two_name_class_list
167190 class_list += added_list
168191 assert class_list == three_name_class_list
@@ -439,9 +462,11 @@ def test_index_not_present(two_name_class_list: 'ClassList', index_value: Union[
439462 (ClassList (InputAttributes (name = 'Eve' ))),
440463 ([InputAttributes (name = 'Eve' )]),
441464 (InputAttributes (name = 'Eve' ),),
465+ (InputAttributes (name = 'Eve' )),
442466])
443467def test_extend (two_name_class_list : 'ClassList' , extended_list : Sequence , three_name_class_list : 'ClassList' ) -> None :
444- """We should be able to extend a ClassList using another ClassList or a sequence"""
468+ """We should be able to extend a ClassList using another ClassList or a sequence. Individual objects should be
469+ wrapped in a list before being added."""
445470 class_list = two_name_class_list
446471 class_list .extend (extended_list )
447472 assert class_list == three_name_class_list
@@ -460,6 +485,30 @@ def test_extend_empty_classlist(extended_list: Sequence, one_name_class_list: 'C
460485 assert isinstance (extended_list [- 1 ], class_list ._class_handle )
461486
462487
488+ @pytest .mark .parametrize (["new_values" , "expected_classlist" ], [
489+ ({'name' : 'Eve' }, ClassList ([InputAttributes (name = 'Eve' ), InputAttributes (name = 'Bob' )])),
490+ ({'name' : 'John' , 'surname' : 'Luther' },
491+ ClassList ([InputAttributes (name = 'John' , surname = 'Luther' ), InputAttributes (name = 'Bob' )])),
492+ ])
493+ def test_set_fields (two_name_class_list : 'ClassList' , new_values : dict [str , Any ], expected_classlist : 'ClassList' )\
494+ -> None :
495+ """We should be able to set field values in an element of a ClassList using keyword arguments."""
496+ class_list = two_name_class_list
497+ class_list .set_fields (0 , ** new_values )
498+ assert class_list == expected_classlist
499+
500+
501+ @pytest .mark .parametrize ("new_values" , [
502+ ({'name' : 'Bob' }),
503+ ])
504+ def test_set_fields_same_name_field (two_name_class_list : 'ClassList' , new_values : dict [str , Any ]) -> None :
505+ """If we set the name_field of an object in the ClassList to one already defined, we should raise a ValueError."""
506+ with pytest .raises (ValueError , match = f"Input arguments contain the { two_name_class_list .name_field } "
507+ f"'{ new_values [two_name_class_list .name_field ]} ', "
508+ f"which is already specified in the ClassList" ):
509+ two_name_class_list .set_fields (0 , ** new_values )
510+
511+
463512@pytest .mark .parametrize (["class_list" , "expected_names" ], [
464513 (ClassList ([InputAttributes (name = 'Alice' ), InputAttributes (name = 'Bob' )]), ["Alice" , "Bob" ]),
465514 (ClassList ([InputAttributes (id = 'Alice' ), InputAttributes (id = 'Bob' )], name_field = 'id' ), ["Alice" , "Bob" ]),
@@ -563,3 +612,19 @@ def test__get_item_from_name_field(two_name_class_list: 'ClassList',
563612 If the value is not the name_field of an object defined in the ClassList, we should return the value.
564613 """
565614 assert two_name_class_list ._get_item_from_name_field (value ) == expected_output
615+
616+
617+ @pytest .mark .parametrize (["input_list" , "expected_type" ], [
618+ ([InputAttributes (name = 'Alice' )], InputAttributes ),
619+ ([InputAttributes (name = 'Alice' ), SubInputAttributes (name = 'Bob' )], InputAttributes ),
620+ ([SubInputAttributes (name = 'Alice' ), InputAttributes (name = 'Bob' )], InputAttributes ),
621+ ([SubInputAttributes (name = 'Alice' ), SubInputAttributes (name = 'Bob' )], SubInputAttributes ),
622+ ([SubInputAttributes (name = 'Alice' ), SubInputAttributes (name = 'Bob' ), InputAttributes (name = 'Eve' )], InputAttributes ),
623+ ([InputAttributes (name = 'Alice' ), dict (name = 'Bob' )], InputAttributes ),
624+ ([dict (name = 'Alice' ), InputAttributes (name = 'Bob' )], dict ),
625+ ])
626+ def test_determine_class_handle (input_list : 'ClassList' , expected_type : type ) -> None :
627+ """The _class_handle for the ClassList should be the type that satisfies the condition "isinstance(element, type)"
628+ for all elements in the ClassList.
629+ """
630+ assert ClassList ._determine_class_handle (input_list ) == expected_type
0 commit comments