示例#1
0
class TableTestCase(unittest.TestCase):
    def setUp(self):
        self.table = Table(fields={
            "name": rows.fields.TextField,
            "birthdate": rows.fields.DateField
        })
        self.first_row = {
            "name": "Álvaro Justen",
            "birthdate": datetime.date(1987, 4, 29),
        }
        self.table.append(self.first_row)
        self.table.append({
            "name": "Somebody",
            "birthdate": datetime.date(1990, 2, 1)
        })
        self.table.append({"name": "Douglas Adams", "birthdate": "1952-03-11"})

    def test_table_init_slug_creation_on_fields(self):
        table = rows.Table(fields=collections.OrderedDict([(
            'Query Occurrence"( % ),"First Seen', rows.fields.FloatField)]))

        self.assertIn("query_occurrence_first_seen", table.fields)

    def test_Table_is_present_on_main_namespace(self):
        self.assertIn("Table", dir(rows))
        self.assertIs(Table, rows.Table)

    def test_table_iteration(self):
        # TODO: may test with all field types (using tests.utils.table)

        table_rows = [row for row in self.table]
        self.assertEqual(len(table_rows), 3)
        self.assertEqual(table_rows[0].name, "Álvaro Justen")
        self.assertEqual(table_rows[0].birthdate, datetime.date(1987, 4, 29))
        self.assertEqual(table_rows[1].name, "Somebody")
        self.assertEqual(table_rows[1].birthdate, datetime.date(1990, 2, 1))
        self.assertEqual(table_rows[2].name, "Douglas Adams")
        self.assertEqual(table_rows[2].birthdate, datetime.date(1952, 3, 11))

    def test_table_slicing(self):
        self.assertEqual(len(self.table[::2]), 2)
        self.assertEqual(self.table[::2][0].name, "Álvaro Justen")

    def test_table_slicing_error(self):
        with self.assertRaises(ValueError) as context_manager:
            self.table[[1]]
        self.assertEqual(type(context_manager.exception), ValueError)

    def test_table_insert_row(self):
        self.table.insert(1, {
            "name": "Grace Hopper",
            "birthdate": datetime.date(1909, 12, 9)
        })
        self.assertEqual(self.table[1].name, "Grace Hopper")

    def test_table_append_error(self):
        # TODO: may mock these validations and test only on *Field tests
        with self.assertRaises(ValueError) as context_manager:
            self.table.append({
                "name": "Álvaro Justen".encode("utf-8"),
                "birthdate": "1987-04-29"
            })
        self.assertEqual(type(context_manager.exception), ValueError)
        self.assertEqual(context_manager.exception.args[0],
                         "Binary is not supported")

        with self.assertRaises(ValueError) as context_manager:
            self.table.append({"name": "Álvaro Justen", "birthdate": "WRONG"})
        self.assertEqual(type(context_manager.exception), ValueError)
        self.assertIn("does not match format",
                      context_manager.exception.args[0])

    def test_table_getitem_invalid_type(self):
        with self.assertRaises(ValueError) as exception_context:
            self.table[3.14]
        self.assertEqual(exception_context.exception.args[0],
                         "Unsupported key type: float")

        with self.assertRaises(ValueError) as exception_context:
            self.table[b"name"]
        self.assertEqual(
            exception_context.exception.args[0],
            "Unsupported key type: {}".format(binary_type_name),
        )

    def test_table_getitem_column_doesnt_exist(self):
        with self.assertRaises(KeyError) as exception_context:
            self.table["doesnt-exist"]

        self.assertEqual(exception_context.exception.args[0], "doesnt-exist")

    def test_table_getitem_column_happy_path(self):
        expected_values = ["Álvaro Justen", "Somebody", "Douglas Adams"]
        self.assertEqual(self.table["name"], expected_values)

        expected_values = [
            datetime.date(1987, 4, 29),
            datetime.date(1990, 2, 1),
            datetime.date(1952, 3, 11),
        ]
        self.assertEqual(self.table["birthdate"], expected_values)

    def test_table_setitem_row(self):
        self.first_row["name"] = "turicas"
        self.first_row["birthdate"] = datetime.date(2000, 1, 1)
        self.table[0] = self.first_row
        self.assertEqual(self.table[0].name, "turicas")
        self.assertEqual(self.table[0].birthdate, datetime.date(2000, 1, 1))

    def test_field_names_and_types(self):
        self.assertEqual(self.table.field_names,
                         list(self.table.fields.keys()))
        self.assertEqual(self.table.field_types,
                         list(self.table.fields.values()))

    def test_table_setitem_column_happy_path_new_column(self):
        number_of_fields = len(self.table.fields)
        self.assertEqual(len(self.table), 3)

        self.table["user_id"] = [4, 5, 6]

        self.assertEqual(len(self.table), 3)
        self.assertEqual(len(self.table.fields), number_of_fields + 1)

        self.assertIn("user_id", self.table.fields)
        self.assertIs(self.table.fields["user_id"], rows.fields.IntegerField)
        self.assertEqual(self.table[0].user_id, 4)
        self.assertEqual(self.table[1].user_id, 5)
        self.assertEqual(self.table[2].user_id, 6)

    def test_table_setitem_column_happy_path_replace_column(self):
        number_of_fields = len(self.table.fields)
        self.assertEqual(len(self.table), 3)

        self.table["name"] = [4, 5, 6]  # change values *and* type

        self.assertEqual(len(self.table), 3)
        self.assertEqual(len(self.table.fields), number_of_fields)

        self.assertIn("name", self.table.fields)
        self.assertIs(self.table.fields["name"], rows.fields.IntegerField)
        self.assertEqual(self.table[0].name, 4)
        self.assertEqual(self.table[1].name, 5)
        self.assertEqual(self.table[2].name, 6)

    def test_table_setitem_column_slug_field_name(self):
        self.assertNotIn("user_id", self.table.fields)
        self.table["User ID"] = [4, 5, 6]
        self.assertIn("user_id", self.table.fields)

    def test_table_setitem_column_invalid_length(self):
        number_of_fields = len(self.table.fields)
        self.assertEqual(len(self.table), 3)

        with self.assertRaises(ValueError) as exception_context:
            self.table["user_id"] = [4, 5]  # list len should be 3

        self.assertEqual(len(self.table), 3)
        self.assertEqual(len(self.table.fields), number_of_fields)
        self.assertEqual(
            exception_context.exception.args[0],
            "Values length (2) should be the same as Table "
            "length (3)",
        )

    def test_table_setitem_invalid_type(self):
        fields = self.table.fields.copy()
        self.assertEqual(len(self.table), 3)

        with self.assertRaises(ValueError) as exception_context:
            self.table[3.14] = []

        self.assertEqual(len(self.table), 3)  # should not add any row
        self.assertDictEqual(fields, self.table.fields)  # should not add field
        self.assertEqual(exception_context.exception.args[0],
                         "Unsupported key type: float")

        with self.assertRaises(ValueError) as exception_context:
            self.table[b"some_value"] = []

        self.assertEqual(len(self.table), 3)  # should not add any row
        self.assertDictEqual(fields, self.table.fields)  # should not add field
        self.assertEqual(
            exception_context.exception.args[0],
            "Unsupported key type: {}".format(binary_type_name),
        )

    def test_table_delitem_row(self):
        table_rows = [row for row in self.table]
        before = len(self.table)
        del self.table[0]
        after = len(self.table)
        self.assertEqual(after, before - 1)
        for row, expected_row in zip(self.table, table_rows[1:]):
            self.assertEqual(row, expected_row)

    def test_table_delitem_column_doesnt_exist(self):
        with self.assertRaises(KeyError) as exception_context:
            del self.table["doesnt-exist"]

        self.assertEqual(exception_context.exception.args[0], "doesnt-exist")

    def test_table_delitem_column_happy_path(self):
        fields = self.table.fields.copy()
        self.assertEqual(len(self.table), 3)

        del self.table["name"]

        self.assertEqual(len(self.table), 3)  # should not del any row
        self.assertEqual(len(self.table.fields), len(fields) - 1)

        self.assertDictEqual(dict(self.table[0]._asdict()),
                             {"birthdate": datetime.date(1987, 4, 29)})
        self.assertDictEqual(dict(self.table[1]._asdict()),
                             {"birthdate": datetime.date(1990, 2, 1)})
        self.assertDictEqual(dict(self.table[2]._asdict()),
                             {"birthdate": datetime.date(1952, 3, 11)})

    def test_table_delitem_column_invalid_type(self):
        fields = self.table.fields.copy()
        self.assertEqual(len(self.table), 3)

        with self.assertRaises(ValueError) as exception_context:
            del self.table[3.14]

        self.assertEqual(len(self.table), 3)  # should not del any row
        self.assertDictEqual(fields, self.table.fields)  # should not del field
        self.assertEqual(exception_context.exception.args[0],
                         "Unsupported key type: float")

        with self.assertRaises(ValueError) as exception_context:
            self.table[b"name"] = []  # 'name' actually exists

        self.assertEqual(len(self.table), 3)  # should not del any row
        self.assertDictEqual(fields, self.table.fields)  # should not del field
        self.assertEqual(
            exception_context.exception.args[0],
            "Unsupported key type: {}".format(binary_type_name),
        )

    def test_table_add(self):
        self.assertIs(self.table + 0, self.table)
        self.assertIs(0 + self.table, self.table)

        new_table = self.table + self.table
        self.assertEqual(new_table.fields, self.table.fields)
        self.assertEqual(len(new_table), 2 * len(self.table))
        self.assertEqual(list(new_table), list(self.table) * 2)

    def test_table_add_error(self):
        with self.assertRaises(ValueError):
            self.table + 1
        with self.assertRaises(ValueError):
            1 + self.table

    def test_table_order_by(self):
        with self.assertRaises(ValueError):
            self.table.order_by("doesnt_exist")

        before = [row.birthdate for row in self.table]
        self.table.order_by("birthdate")
        after = [row.birthdate for row in self.table]
        self.assertNotEqual(before, after)
        self.assertEqual(sorted(before), after)

        self.table.order_by("-birthdate")
        final = [row.birthdate for row in self.table]
        self.assertEqual(final, list(reversed(after)))

        self.table.order_by("name")
        expected_rows = [
            {
                "name": "Douglas Adams",
                "birthdate": datetime.date(1952, 3, 11)
            },
            {
                "name": "Somebody",
                "birthdate": datetime.date(1990, 2, 1)
            },
            {
                "name": "Álvaro Justen",
                "birthdate": datetime.date(1987, 4, 29)
            },
        ]
        for expected_row, row in zip(expected_rows, self.table):
            self.assertEqual(expected_row, dict(row._asdict()))

    def test_table_repr(self):
        expected = "<rows.Table 2 fields, 3 rows>"
        self.assertEqual(expected, repr(self.table))

    def test_table_add_should_not_iterate_over_rows(self):
        table1 = rows.Table(fields={
            "f1": rows.fields.IntegerField,
            "f2": rows.fields.FloatField
        })
        table2 = rows.Table(fields={
            "f1": rows.fields.IntegerField,
            "f2": rows.fields.FloatField
        })
        table1._rows = mock.Mock()
        table1._rows.__add__ = mock.Mock()
        table1._rows.__iter__ = mock.Mock()
        table2._rows = mock.Mock()
        table2._rows.__add__ = mock.Mock()
        table2._rows.__iter__ = mock.Mock()

        self.assertFalse(table1._rows.__add__.called)
        self.assertFalse(table2._rows.__add__.called)
        self.assertFalse(table1._rows.__iter__.called)
        self.assertFalse(table2._rows.__iter__.called)
        table1 + table2
        self.assertTrue(table1._rows.__add__.called)
        self.assertFalse(table2._rows.__add__.called)
        self.assertFalse(table1._rows.__iter__.called)
        self.assertFalse(table2._rows.__iter__.called)
示例#2
0
class TableTestCase(unittest.TestCase):
    def setUp(self):
        self.table = Table(fields={
            'name': rows.fields.TextField,
            'birthdate': rows.fields.DateField,
        })
        self.first_row = {
            'name': 'Álvaro Justen',
            'birthdate': datetime.date(1987, 4, 29)
        }
        self.table.append(self.first_row)
        self.table.append({
            'name': 'Somebody',
            'birthdate': datetime.date(1990, 2, 1)
        })
        self.table.append({'name': 'Douglas Adams', 'birthdate': '1952-03-11'})

    def test_Table_is_present_on_main_namespace(self):
        self.assertIn('Table', dir(rows))
        self.assertIs(Table, rows.Table)

    def test_table_iteration(self):
        # TODO: may test with all field types (using tests.utils.table)

        table_rows = [row for row in self.table]
        self.assertEqual(len(table_rows), 3)
        self.assertEqual(table_rows[0].name, 'Álvaro Justen')
        self.assertEqual(table_rows[0].birthdate, datetime.date(1987, 4, 29))
        self.assertEqual(table_rows[1].name, 'Somebody')
        self.assertEqual(table_rows[1].birthdate, datetime.date(1990, 2, 1))
        self.assertEqual(table_rows[2].name, 'Douglas Adams')
        self.assertEqual(table_rows[2].birthdate, datetime.date(1952, 3, 11))

    def test_table_slicing(self):
        self.assertEqual(len(self.table[::2]), 2)
        self.assertEqual(self.table[::2][0].name, 'Álvaro Justen')

    def test_table_slicing_error(self):
        with self.assertRaises(ValueError) as context_manager:
            self.table[[1]]
        self.assertEqual(type(context_manager.exception), ValueError)

    def test_table_insert_row(self):
        self.table.insert(1, {
            'name': 'Grace Hopper',
            'birthdate': datetime.date(1909, 12, 9)
        })
        self.assertEqual(self.table[1].name, 'Grace Hopper')

    def test_table_append_error(self):
        # TODO: may mock these validations and test only on *Field tests
        with self.assertRaises(ValueError) as context_manager:
            self.table.append({
                'name': 'Álvaro Justen'.encode('utf-8'),
                'birthdate': '1987-04-29'
            })
        self.assertEqual(type(context_manager.exception), ValueError)
        self.assertEqual(context_manager.exception.args[0],
                         'Binary is not supported')

        with self.assertRaises(ValueError) as context_manager:
            self.table.append({'name': 'Álvaro Justen', 'birthdate': 'WRONG'})
        self.assertEqual(type(context_manager.exception), ValueError)
        self.assertIn('does not match format',
                      context_manager.exception.args[0])

    def test_table_getitem_invalid_type(self):
        with self.assertRaises(ValueError) as exception_context:
            self.table[3.14]
        self.assertEqual(exception_context.exception.args[0],
                         'Unsupported key type: float')

        with self.assertRaises(ValueError) as exception_context:
            self.table[b'name']
        self.assertEqual(exception_context.exception.args[0],
                         'Unsupported key type: {}'.format(binary_type_name))

    def test_table_getitem_column_doesnt_exist(self):
        with self.assertRaises(KeyError) as exception_context:
            self.table['doesnt-exist']

        self.assertEqual(exception_context.exception.args[0], 'doesnt-exist')

    def test_table_getitem_column_happy_path(self):
        expected_values = ['Álvaro Justen', 'Somebody', 'Douglas Adams']
        self.assertEqual(self.table['name'], expected_values)

        expected_values = [
            datetime.date(1987, 4, 29),
            datetime.date(1990, 2, 1),
            datetime.date(1952, 3, 11)
        ]
        self.assertEqual(self.table['birthdate'], expected_values)

    def test_table_setitem_row(self):
        self.first_row['name'] = 'turicas'
        self.first_row['birthdate'] = datetime.date(2000, 1, 1)
        self.table[0] = self.first_row
        self.assertEqual(self.table[0].name, 'turicas')
        self.assertEqual(self.table[0].birthdate, datetime.date(2000, 1, 1))

    def test_field_names_and_types(self):
        self.assertEqual(self.table.field_names,
                         list(self.table.fields.keys()))
        self.assertEqual(self.table.field_types,
                         list(self.table.fields.values()))

    def test_table_setitem_column_happy_path_new_column(self):
        number_of_fields = len(self.table.fields)
        self.assertEqual(len(self.table), 3)

        self.table['user_id'] = [4, 5, 6]

        self.assertEqual(len(self.table), 3)
        self.assertEqual(len(self.table.fields), number_of_fields + 1)

        self.assertIn('user_id', self.table.fields)
        self.assertIs(self.table.fields['user_id'], rows.fields.IntegerField)
        self.assertEqual(self.table[0].user_id, 4)
        self.assertEqual(self.table[1].user_id, 5)
        self.assertEqual(self.table[2].user_id, 6)

    def test_table_setitem_column_happy_path_replace_column(self):
        number_of_fields = len(self.table.fields)
        self.assertEqual(len(self.table), 3)

        self.table['name'] = [4, 5, 6]  # change values *and* type

        self.assertEqual(len(self.table), 3)
        self.assertEqual(len(self.table.fields), number_of_fields)

        self.assertIn('name', self.table.fields)
        self.assertIs(self.table.fields['name'], rows.fields.IntegerField)
        self.assertEqual(self.table[0].name, 4)
        self.assertEqual(self.table[1].name, 5)
        self.assertEqual(self.table[2].name, 6)

    def test_table_setitem_column_slug_field_name(self):
        self.assertNotIn('user_id', self.table.fields)
        self.table['User ID'] = [4, 5, 6]
        self.assertIn('user_id', self.table.fields)

    def test_table_setitem_column_invalid_length(self):
        number_of_fields = len(self.table.fields)
        self.assertEqual(len(self.table), 3)

        with self.assertRaises(ValueError) as exception_context:
            self.table['user_id'] = [4, 5]  # list len should be 3

        self.assertEqual(len(self.table), 3)
        self.assertEqual(len(self.table.fields), number_of_fields)
        self.assertEqual(
            exception_context.exception.args[0],
            'Values length (2) should be the same as Table '
            'length (3)')

    def test_table_setitem_invalid_type(self):
        fields = self.table.fields.copy()
        self.assertEqual(len(self.table), 3)

        with self.assertRaises(ValueError) as exception_context:
            self.table[3.14] = []

        self.assertEqual(len(self.table), 3)  # should not add any row
        self.assertDictEqual(fields, self.table.fields)  # should not add field
        self.assertEqual(exception_context.exception.args[0],
                         'Unsupported key type: float')

        with self.assertRaises(ValueError) as exception_context:
            self.table[b'some_value'] = []

        self.assertEqual(len(self.table), 3)  # should not add any row
        self.assertDictEqual(fields, self.table.fields)  # should not add field
        self.assertEqual(exception_context.exception.args[0],
                         'Unsupported key type: {}'.format(binary_type_name))

    def test_table_delitem_row(self):
        table_rows = [row for row in self.table]
        before = len(self.table)
        del self.table[0]
        after = len(self.table)
        self.assertEqual(after, before - 1)
        for row, expected_row in zip(self.table, table_rows[1:]):
            self.assertEqual(row, expected_row)

    def test_table_delitem_column_doesnt_exist(self):
        with self.assertRaises(KeyError) as exception_context:
            del self.table['doesnt-exist']

        self.assertEqual(exception_context.exception.args[0], 'doesnt-exist')

    def test_table_delitem_column_happy_path(self):
        fields = self.table.fields.copy()
        self.assertEqual(len(self.table), 3)

        del self.table['name']

        self.assertEqual(len(self.table), 3)  # should not del any row
        self.assertEqual(len(self.table.fields), len(fields) - 1)

        self.assertDictEqual(dict(self.table[0]._asdict()),
                             {'birthdate': datetime.date(1987, 4, 29)})
        self.assertDictEqual(dict(self.table[1]._asdict()),
                             {'birthdate': datetime.date(1990, 2, 1)})
        self.assertDictEqual(dict(self.table[2]._asdict()),
                             {'birthdate': datetime.date(1952, 3, 11)})

    def test_table_delitem_column_invalid_type(self):
        fields = self.table.fields.copy()
        self.assertEqual(len(self.table), 3)

        with self.assertRaises(ValueError) as exception_context:
            del self.table[3.14]

        self.assertEqual(len(self.table), 3)  # should not del any row
        self.assertDictEqual(fields, self.table.fields)  # should not del field
        self.assertEqual(exception_context.exception.args[0],
                         'Unsupported key type: float')

        with self.assertRaises(ValueError) as exception_context:
            self.table[b'name'] = []  # 'name' actually exists

        self.assertEqual(len(self.table), 3)  # should not del any row
        self.assertDictEqual(fields, self.table.fields)  # should not del field
        self.assertEqual(exception_context.exception.args[0],
                         'Unsupported key type: {}'.format(binary_type_name))

    def test_table_add(self):
        self.assertIs(self.table + 0, self.table)
        self.assertIs(0 + self.table, self.table)

        new_table = self.table + self.table
        self.assertEqual(new_table.fields, self.table.fields)
        self.assertEqual(len(new_table), 2 * len(self.table))
        self.assertEqual(list(new_table), list(self.table) * 2)

    def test_table_add_error(self):
        with self.assertRaises(ValueError):
            self.table + 1
        with self.assertRaises(ValueError):
            1 + self.table

    def test_table_order_by(self):
        with self.assertRaises(ValueError):
            self.table.order_by('doesnt_exist')

        before = [row.birthdate for row in self.table]
        self.table.order_by('birthdate')
        after = [row.birthdate for row in self.table]
        self.assertNotEqual(before, after)
        self.assertEqual(sorted(before), after)

        self.table.order_by('-birthdate')
        final = [row.birthdate for row in self.table]
        self.assertEqual(final, list(reversed(after)))

        self.table.order_by('name')
        expected_rows = [{
            'name': 'Douglas Adams',
            'birthdate': datetime.date(1952, 3, 11)
        }, {
            'name': 'Somebody',
            'birthdate': datetime.date(1990, 2, 1)
        }, {
            'name': 'Álvaro Justen',
            'birthdate': datetime.date(1987, 4, 29)
        }]
        for expected_row, row in zip(expected_rows, self.table):
            self.assertEqual(expected_row, dict(row._asdict()))

    def test_table_repr(self):
        expected = '<rows.Table 2 fields, 3 rows>'
        self.assertEqual(expected, repr(self.table))

    def test_table_add_time(self):
        '''rows.Table.__add__ should be constant time

        To test it we double table size for each round and then compare the
        standard deviation to the mean (it will be almost the mean if the
        algorithm is not fast enough and almost 10% of the mean if it's good).
        '''
        rounds = []
        table = utils.table
        for _ in range(5):
            start = time.time()
            table = table + table
            end = time.time()
            rounds.append(end - start)

        mean = sum(rounds) / len(rounds)
        stdev = math.sqrt((1.0 / (len(rounds) - 1)) * sum(
            (value - mean)**2 for value in rounds))
        self.assertTrue(0.2 * mean > stdev)
示例#3
0
class TableTestCase(unittest.TestCase):
    def setUp(self):
        self.table = Table(
            fields={"name": rows.fields.TextField, "birthdate": rows.fields.DateField}
        )
        self.first_row = {
            "name": "Álvaro Justen",
            "birthdate": datetime.date(1987, 4, 29),
        }
        self.table.append(self.first_row)
        self.table.append({"name": "Somebody", "birthdate": datetime.date(1990, 2, 1)})
        self.table.append({"name": "Douglas Adams", "birthdate": "1952-03-11"})

    def test_table_init_slug_creation_on_fields(self):
        table = rows.Table(
            fields=collections.OrderedDict(
                [('Query Occurrence"( % ),"First Seen', rows.fields.FloatField)]
            )
        )

        self.assertIn("query_occurrence_first_seen", table.fields)

    def test_Table_is_present_on_main_namespace(self):
        self.assertIn("Table", dir(rows))
        self.assertIs(Table, rows.Table)

    def test_table_iteration(self):
        # TODO: may test with all field types (using tests.utils.table)

        table_rows = [row for row in self.table]
        self.assertEqual(len(table_rows), 3)
        self.assertEqual(table_rows[0].name, "Álvaro Justen")
        self.assertEqual(table_rows[0].birthdate, datetime.date(1987, 4, 29))
        self.assertEqual(table_rows[1].name, "Somebody")
        self.assertEqual(table_rows[1].birthdate, datetime.date(1990, 2, 1))
        self.assertEqual(table_rows[2].name, "Douglas Adams")
        self.assertEqual(table_rows[2].birthdate, datetime.date(1952, 3, 11))

    def test_table_slicing(self):
        self.assertEqual(len(self.table[::2]), 2)
        self.assertEqual(self.table[::2][0].name, "Álvaro Justen")

    def test_table_slicing_error(self):
        with self.assertRaises(ValueError) as context_manager:
            self.table[[1]]
        self.assertEqual(type(context_manager.exception), ValueError)

    def test_table_insert_row(self):
        self.table.insert(
            1, {"name": "Grace Hopper", "birthdate": datetime.date(1909, 12, 9)}
        )
        self.assertEqual(self.table[1].name, "Grace Hopper")

    def test_table_append_error(self):
        # TODO: may mock these validations and test only on *Field tests
        with self.assertRaises(ValueError) as context_manager:
            self.table.append(
                {"name": "Álvaro Justen".encode("utf-8"), "birthdate": "1987-04-29"}
            )
        self.assertEqual(type(context_manager.exception), ValueError)
        self.assertEqual(context_manager.exception.args[0], "Binary is not supported")

        with self.assertRaises(ValueError) as context_manager:
            self.table.append({"name": "Álvaro Justen", "birthdate": "WRONG"})
        self.assertEqual(type(context_manager.exception), ValueError)
        self.assertIn("does not match format", context_manager.exception.args[0])

    def test_table_getitem_invalid_type(self):
        with self.assertRaises(ValueError) as exception_context:
            self.table[3.14]
        self.assertEqual(
            exception_context.exception.args[0], "Unsupported key type: float"
        )

        with self.assertRaises(ValueError) as exception_context:
            self.table[b"name"]
        self.assertEqual(
            exception_context.exception.args[0],
            "Unsupported key type: {}".format(binary_type_name),
        )

    def test_table_getitem_column_doesnt_exist(self):
        with self.assertRaises(KeyError) as exception_context:
            self.table["doesnt-exist"]

        self.assertEqual(exception_context.exception.args[0], "doesnt-exist")

    def test_table_getitem_column_happy_path(self):
        expected_values = ["Álvaro Justen", "Somebody", "Douglas Adams"]
        self.assertEqual(self.table["name"], expected_values)

        expected_values = [
            datetime.date(1987, 4, 29),
            datetime.date(1990, 2, 1),
            datetime.date(1952, 3, 11),
        ]
        self.assertEqual(self.table["birthdate"], expected_values)

    def test_table_setitem_row(self):
        self.first_row["name"] = "turicas"
        self.first_row["birthdate"] = datetime.date(2000, 1, 1)
        self.table[0] = self.first_row
        self.assertEqual(self.table[0].name, "turicas")
        self.assertEqual(self.table[0].birthdate, datetime.date(2000, 1, 1))

    def test_field_names_and_types(self):
        self.assertEqual(self.table.field_names, list(self.table.fields.keys()))
        self.assertEqual(self.table.field_types, list(self.table.fields.values()))

    def test_table_setitem_column_happy_path_new_column(self):
        number_of_fields = len(self.table.fields)
        self.assertEqual(len(self.table), 3)

        self.table["user_id"] = [4, 5, 6]

        self.assertEqual(len(self.table), 3)
        self.assertEqual(len(self.table.fields), number_of_fields + 1)

        self.assertIn("user_id", self.table.fields)
        self.assertIs(self.table.fields["user_id"], rows.fields.IntegerField)
        self.assertEqual(self.table[0].user_id, 4)
        self.assertEqual(self.table[1].user_id, 5)
        self.assertEqual(self.table[2].user_id, 6)

    def test_table_setitem_column_happy_path_replace_column(self):
        number_of_fields = len(self.table.fields)
        self.assertEqual(len(self.table), 3)

        self.table["name"] = [4, 5, 6]  # change values *and* type

        self.assertEqual(len(self.table), 3)
        self.assertEqual(len(self.table.fields), number_of_fields)

        self.assertIn("name", self.table.fields)
        self.assertIs(self.table.fields["name"], rows.fields.IntegerField)
        self.assertEqual(self.table[0].name, 4)
        self.assertEqual(self.table[1].name, 5)
        self.assertEqual(self.table[2].name, 6)

    def test_table_setitem_column_slug_field_name(self):
        self.assertNotIn("user_id", self.table.fields)
        self.table["User ID"] = [4, 5, 6]
        self.assertIn("user_id", self.table.fields)

    def test_table_setitem_column_invalid_length(self):
        number_of_fields = len(self.table.fields)
        self.assertEqual(len(self.table), 3)

        with self.assertRaises(ValueError) as exception_context:
            self.table["user_id"] = [4, 5]  # list len should be 3

        self.assertEqual(len(self.table), 3)
        self.assertEqual(len(self.table.fields), number_of_fields)
        self.assertEqual(
            exception_context.exception.args[0],
            "Values length (2) should be the same as Table " "length (3)",
        )

    def test_table_setitem_invalid_type(self):
        fields = self.table.fields.copy()
        self.assertEqual(len(self.table), 3)

        with self.assertRaises(ValueError) as exception_context:
            self.table[3.14] = []

        self.assertEqual(len(self.table), 3)  # should not add any row
        self.assertDictEqual(fields, self.table.fields)  # should not add field
        self.assertEqual(
            exception_context.exception.args[0], "Unsupported key type: float"
        )

        with self.assertRaises(ValueError) as exception_context:
            self.table[b"some_value"] = []

        self.assertEqual(len(self.table), 3)  # should not add any row
        self.assertDictEqual(fields, self.table.fields)  # should not add field
        self.assertEqual(
            exception_context.exception.args[0],
            "Unsupported key type: {}".format(binary_type_name),
        )

    def test_table_delitem_row(self):
        table_rows = [row for row in self.table]
        before = len(self.table)
        del self.table[0]
        after = len(self.table)
        self.assertEqual(after, before - 1)
        for row, expected_row in zip(self.table, table_rows[1:]):
            self.assertEqual(row, expected_row)

    def test_table_delitem_column_doesnt_exist(self):
        with self.assertRaises(KeyError) as exception_context:
            del self.table["doesnt-exist"]

        self.assertEqual(exception_context.exception.args[0], "doesnt-exist")

    def test_table_delitem_column_happy_path(self):
        fields = self.table.fields.copy()
        self.assertEqual(len(self.table), 3)

        del self.table["name"]

        self.assertEqual(len(self.table), 3)  # should not del any row
        self.assertEqual(len(self.table.fields), len(fields) - 1)

        self.assertDictEqual(
            dict(self.table[0]._asdict()), {"birthdate": datetime.date(1987, 4, 29)}
        )
        self.assertDictEqual(
            dict(self.table[1]._asdict()), {"birthdate": datetime.date(1990, 2, 1)}
        )
        self.assertDictEqual(
            dict(self.table[2]._asdict()), {"birthdate": datetime.date(1952, 3, 11)}
        )

    def test_table_delitem_column_invalid_type(self):
        fields = self.table.fields.copy()
        self.assertEqual(len(self.table), 3)

        with self.assertRaises(ValueError) as exception_context:
            del self.table[3.14]

        self.assertEqual(len(self.table), 3)  # should not del any row
        self.assertDictEqual(fields, self.table.fields)  # should not del field
        self.assertEqual(
            exception_context.exception.args[0], "Unsupported key type: float"
        )

        with self.assertRaises(ValueError) as exception_context:
            self.table[b"name"] = []  # 'name' actually exists

        self.assertEqual(len(self.table), 3)  # should not del any row
        self.assertDictEqual(fields, self.table.fields)  # should not del field
        self.assertEqual(
            exception_context.exception.args[0],
            "Unsupported key type: {}".format(binary_type_name),
        )

    def test_table_add(self):
        self.assertIs(self.table + 0, self.table)
        self.assertIs(0 + self.table, self.table)

        new_table = self.table + self.table
        self.assertEqual(new_table.fields, self.table.fields)
        self.assertEqual(len(new_table), 2 * len(self.table))
        self.assertEqual(list(new_table), list(self.table) * 2)

    def test_table_add_error(self):
        with self.assertRaises(ValueError):
            self.table + 1
        with self.assertRaises(ValueError):
            1 + self.table

    def test_table_order_by(self):
        with self.assertRaises(ValueError):
            self.table.order_by("doesnt_exist")

        before = [row.birthdate for row in self.table]
        self.table.order_by("birthdate")
        after = [row.birthdate for row in self.table]
        self.assertNotEqual(before, after)
        self.assertEqual(sorted(before), after)

        self.table.order_by("-birthdate")
        final = [row.birthdate for row in self.table]
        self.assertEqual(final, list(reversed(after)))

        self.table.order_by("name")
        expected_rows = [
            {"name": "Douglas Adams", "birthdate": datetime.date(1952, 3, 11)},
            {"name": "Somebody", "birthdate": datetime.date(1990, 2, 1)},
            {"name": "Álvaro Justen", "birthdate": datetime.date(1987, 4, 29)},
        ]
        for expected_row, row in zip(expected_rows, self.table):
            self.assertEqual(expected_row, dict(row._asdict()))

    def test_table_repr(self):
        expected = "<rows.Table 2 fields, 3 rows>"
        self.assertEqual(expected, repr(self.table))

    def test_table_add_should_not_iterate_over_rows(self):
        table1 = rows.Table(
            fields={"f1": rows.fields.IntegerField, "f2": rows.fields.FloatField}
        )
        table2 = rows.Table(
            fields={"f1": rows.fields.IntegerField, "f2": rows.fields.FloatField}
        )
        table1._rows = mock.Mock()
        table1._rows.__add__ = mock.Mock()
        table1._rows.__iter__ = mock.Mock()
        table2._rows = mock.Mock()
        table2._rows.__add__ = mock.Mock()
        table2._rows.__iter__ = mock.Mock()

        self.assertFalse(table1._rows.__add__.called)
        self.assertFalse(table2._rows.__add__.called)
        self.assertFalse(table1._rows.__iter__.called)
        self.assertFalse(table2._rows.__iter__.called)
        table1 + table2
        self.assertTrue(table1._rows.__add__.called)
        self.assertFalse(table2._rows.__add__.called)
        self.assertFalse(table1._rows.__iter__.called)
        self.assertFalse(table2._rows.__iter__.called)
示例#4
0
class TableTestCase(unittest.TestCase):
    def setUp(self):
        self.table = Table(fields={
            'name': rows.fields.TextField,
            'birthdate': rows.fields.DateField,
        })
        self.first_row = {
            'name': u'Álvaro Justen',
            'birthdate': datetime.date(1987, 4, 29)
        }
        self.table.append(self.first_row)
        self.table.append({
            'name': u'Somebody',
            'birthdate': datetime.date(1990, 2, 1)
        })
        self.table.append({
            'name': u'Douglas Adams',
            'birthdate': '1952-03-11'
        })

    def test_Table_is_present_on_main_namespace(self):
        self.assertIn('Table', dir(rows))
        self.assertIs(Table, rows.Table)

    def test_table_iteration(self):
        # TODO: may test with all field types (using tests.utils.table)

        table_rows = [row for row in self.table]
        self.assertEqual(len(table_rows), 3)
        self.assertEqual(table_rows[0].name, u'Álvaro Justen')
        self.assertEqual(table_rows[0].birthdate, datetime.date(1987, 4, 29))
        self.assertEqual(table_rows[1].name, u'Somebody')
        self.assertEqual(table_rows[1].birthdate, datetime.date(1990, 2, 1))
        self.assertEqual(table_rows[2].name, u'Douglas Adams')
        self.assertEqual(table_rows[2].birthdate, datetime.date(1952, 3, 11))

    def test_table_slicing(self):
        self.assertEqual(len(self.table[::2]), 2)
        self.assertEqual(self.table[::2][0].name, u'Álvaro Justen')

    def test_table_slicing_error(self):
        with self.assertRaises(ValueError) as context_manager:
            self.table[[1]]
        self.assertEqual(type(context_manager.exception), ValueError)

    def test_table_insert_row(self):
        self.table.insert(1, {
            'name': u'Grace Hopper',
            'birthdate': datetime.date(1909, 12, 9)
        })
        self.assertEqual(self.table[1].name, u'Grace Hopper')

    def test_table_append_error(self):
        # TODO: may mock these validations and test only on *Field tests
        with self.assertRaises(ValueError) as context_manager:
            self.table.append({
                'name': 'Álvaro Justen'.encode('utf-8'),
                'birthdate': '1987-04-29'
            })
        self.assertEqual(type(context_manager.exception), UnicodeDecodeError)

        with self.assertRaises(ValueError) as context_manager:
            self.table.append({'name': u'Álvaro Justen', 'birthdate': 'WRONG'})
        self.assertEqual(type(context_manager.exception), ValueError)
        self.assertIn('does not match format',
                      context_manager.exception.message)

    def test_table_getitem_invalid_type(self):
        with self.assertRaises(ValueError) as exception_context:
            self.table[3.14]
        self.assertEqual(exception_context.exception.message,
                         'Unsupported key type: float')

        with self.assertRaises(ValueError) as exception_context:
            self.table[b'name']
        self.assertEqual(exception_context.exception.message,
                         'Unsupported key type: str')
        # TODO: should change to 'bytes' on Python3

    def test_table_getitem_column_doesnt_exist(self):
        with self.assertRaises(KeyError) as exception_context:
            self.table['doesnt-exist']

        self.assertEqual(exception_context.exception.message, 'doesnt-exist')

    def test_table_getitem_column_happy_path(self):
        expected_values = ['Álvaro Justen', 'Somebody', 'Douglas Adams']
        self.assertEqual(self.table['name'], expected_values)

        expected_values = [
            datetime.date(1987, 4, 29),
            datetime.date(1990, 2, 1),
            datetime.date(1952, 3, 11)
        ]
        self.assertEqual(self.table['birthdate'], expected_values)

    def test_table_setitem_row(self):
        self.first_row['name'] = 'turicas'
        self.first_row['birthdate'] = datetime.date(2000, 1, 1)
        self.table[0] = self.first_row
        self.assertEqual(self.table[0].name, 'turicas')
        self.assertEqual(self.table[0].birthdate, datetime.date(2000, 1, 1))

    def test_field_names_and_types(self):
        self.assertEqual(self.table.field_names, self.table.fields.keys())
        self.assertEqual(self.table.field_types, self.table.fields.values())

    def test_table_setitem_column_happy_path_new_column(self):
        number_of_fields = len(self.table.fields)
        self.assertEqual(len(self.table), 3)

        self.table['user_id'] = [4, 5, 6]

        self.assertEqual(len(self.table), 3)
        self.assertEqual(len(self.table.fields), number_of_fields + 1)

        self.assertIn('user_id', self.table.fields)
        self.assertIs(self.table.fields['user_id'], rows.fields.IntegerField)
        self.assertEqual(self.table[0].user_id, 4)
        self.assertEqual(self.table[1].user_id, 5)
        self.assertEqual(self.table[2].user_id, 6)

    def test_table_setitem_column_happy_path_replace_column(self):
        number_of_fields = len(self.table.fields)
        self.assertEqual(len(self.table), 3)

        self.table['name'] = [4, 5, 6]  # change values *and* type

        self.assertEqual(len(self.table), 3)
        self.assertEqual(len(self.table.fields), number_of_fields)

        self.assertIn('name', self.table.fields)
        self.assertIs(self.table.fields['name'], rows.fields.IntegerField)
        self.assertEqual(self.table[0].name, 4)
        self.assertEqual(self.table[1].name, 5)
        self.assertEqual(self.table[2].name, 6)

    def test_table_setitem_column_slug_field_name(self):
        self.assertNotIn('user_id', self.table.fields)
        self.table['User ID'] = [4, 5, 6]
        self.assertIn('user_id', self.table.fields)

    def test_table_setitem_column_invalid_length(self):
        number_of_fields = len(self.table.fields)
        self.assertEqual(len(self.table), 3)

        with self.assertRaises(ValueError) as exception_context:
            self.table['user_id'] = [4, 5]  # list len should be 3

        self.assertEqual(len(self.table), 3)
        self.assertEqual(len(self.table.fields), number_of_fields)
        self.assertEqual(
            exception_context.exception.message,
            'Values length (2) should be the same as Table '
            'length (3)')

    def test_table_setitem_invalid_type(self):
        fields = self.table.fields.copy()
        self.assertEqual(len(self.table), 3)

        with self.assertRaises(ValueError) as exception_context:
            self.table[3.14] = []

        self.assertEqual(len(self.table), 3)  # should not add any row
        self.assertDictEqual(fields, self.table.fields)  # should not add field
        self.assertEqual(exception_context.exception.message,
                         'Unsupported key type: float')

        with self.assertRaises(ValueError) as exception_context:
            self.table[b'some_value'] = []

        self.assertEqual(len(self.table), 3)  # should not add any row
        self.assertDictEqual(fields, self.table.fields)  # should not add field
        self.assertEqual(exception_context.exception.message,
                         'Unsupported key type: str')
        # TODO: should change to 'bytes' on Python3

    def test_table_delitem_row(self):
        table_rows = [row for row in self.table]
        before = len(self.table)
        del self.table[0]
        after = len(self.table)
        self.assertEqual(after, before - 1)
        for row, expected_row in zip(self.table, table_rows[1:]):
            self.assertEqual(row, expected_row)

    def test_table_delitem_column_doesnt_exist(self):
        with self.assertRaises(KeyError) as exception_context:
            del self.table['doesnt-exist']

        self.assertEqual(exception_context.exception.message, 'doesnt-exist')

    def test_table_delitem_column_happy_path(self):
        fields = self.table.fields.copy()
        self.assertEqual(len(self.table), 3)

        del self.table['name']

        self.assertEqual(len(self.table), 3)  # should not del any row
        self.assertEqual(len(self.table.fields), len(fields) - 1)

        self.assertDictEqual(dict(self.table[0]._asdict()),
                             {'birthdate': datetime.date(1987, 4, 29)})
        self.assertDictEqual(dict(self.table[1]._asdict()),
                             {'birthdate': datetime.date(1990, 2, 1)})
        self.assertDictEqual(dict(self.table[2]._asdict()),
                             {'birthdate': datetime.date(1952, 3, 11)})

    def test_table_delitem_column_invalid_type(self):
        fields = self.table.fields.copy()
        self.assertEqual(len(self.table), 3)

        with self.assertRaises(ValueError) as exception_context:
            del self.table[3.14]

        self.assertEqual(len(self.table), 3)  # should not del any row
        self.assertDictEqual(fields, self.table.fields)  # should not del field
        self.assertEqual(exception_context.exception.message,
                         'Unsupported key type: float')

        with self.assertRaises(ValueError) as exception_context:
            self.table[b'name'] = []  # u'name' actually exists

        self.assertEqual(len(self.table), 3)  # should not del any row
        self.assertDictEqual(fields, self.table.fields)  # should not del field
        self.assertEqual(exception_context.exception.message,
                         'Unsupported key type: str')
        # TODO: should change to 'bytes' on Python3

    def test_table_add(self):
        self.assertIs(self.table + 0, self.table)
        self.assertIs(0 + self.table, self.table)

        new_table = self.table + self.table
        self.assertEqual(new_table.fields, self.table.fields)
        self.assertEqual(len(new_table), 2 * len(self.table))
        self.assertEqual(list(new_table), list(self.table) * 2)

    def test_table_add_error(self):
        with self.assertRaises(ValueError):
            self.table + 1
        with self.assertRaises(ValueError):
            1 + self.table

    def test_table_order_by(self):
        with self.assertRaises(ValueError):
            self.table.order_by('doesnt_exist')

        before = [row.birthdate for row in self.table]
        self.table.order_by('birthdate')
        after = [row.birthdate for row in self.table]
        self.assertNotEqual(before, after)
        self.assertEqual(sorted(before), after)

        self.table.order_by('-birthdate')
        final = [row.birthdate for row in self.table]
        self.assertEqual(final, list(reversed(after)))

        self.table.order_by('name')
        expected_rows = [{
            'name': 'Douglas Adams',
            'birthdate': datetime.date(1952, 3, 11)
        }, {
            'name': 'Somebody',
            'birthdate': datetime.date(1990, 2, 1)
        }, {
            'name': 'Álvaro Justen',
            'birthdate': datetime.date(1987, 4, 29)
        }]
        for expected_row, row in zip(expected_rows, self.table):
            self.assertEqual(expected_row, dict(row._asdict()))

    def test_table_repr(self):
        expected = '<rows.Table 2 fields, 3 rows>'
        self.assertEqual(expected, repr(self.table))
示例#5
0
class TableTestCase(unittest.TestCase):

    def setUp(self):
        self.table = Table(fields={'name': rows.fields.TextField,
                                   'birthdate': rows.fields.DateField, })
        self.first_row = {'name': 'Álvaro Justen',
                          'birthdate': datetime.date(1987, 4, 29)}
        self.table.append(self.first_row)
        self.table.append({'name': 'Somebody',
                           'birthdate': datetime.date(1990, 2, 1)})
        self.table.append({'name': 'Douglas Adams',
                           'birthdate': '1952-03-11'})

    def test_Table_is_present_on_main_namespace(self):
        self.assertIn('Table', dir(rows))
        self.assertIs(Table, rows.Table)

    def test_table_iteration(self):
        # TODO: may test with all field types (using tests.utils.table)

        table_rows = [row for row in self.table]
        self.assertEqual(len(table_rows), 3)
        self.assertEqual(table_rows[0].name, 'Álvaro Justen')
        self.assertEqual(table_rows[0].birthdate, datetime.date(1987, 4, 29))
        self.assertEqual(table_rows[1].name, 'Somebody')
        self.assertEqual(table_rows[1].birthdate, datetime.date(1990, 2, 1))
        self.assertEqual(table_rows[2].name, 'Douglas Adams')
        self.assertEqual(table_rows[2].birthdate, datetime.date(1952, 3, 11))

    def test_table_slicing(self):
        self.assertEqual(len(self.table[::2]), 2)
        self.assertEqual(self.table[::2][0].name, 'Álvaro Justen')

    def test_table_slicing_error(self):
        with self.assertRaises(ValueError) as context_manager:
            self.table[[1]]
        self.assertEqual(type(context_manager.exception), ValueError)

    def test_table_insert_row(self):
        self.table.insert(1, {'name': 'Grace Hopper',
                              'birthdate': datetime.date(1909, 12, 9)})
        self.assertEqual(self.table[1].name, 'Grace Hopper')

    def test_table_append_error(self):
        # TODO: may mock these validations and test only on *Field tests
        with self.assertRaises(ValueError) as context_manager:
            self.table.append({'name': 'Álvaro Justen'.encode('utf-8'),
                               'birthdate': '1987-04-29'})
        self.assertEqual(type(context_manager.exception), ValueError)
        self.assertEqual(context_manager.exception.args[0],
                         'Binary is not supported')

        with self.assertRaises(ValueError) as context_manager:
            self.table.append({'name': 'Álvaro Justen', 'birthdate': 'WRONG'})
        self.assertEqual(type(context_manager.exception), ValueError)
        self.assertIn('does not match format',
                      context_manager.exception.args[0])

    def test_table_getitem_invalid_type(self):
        with self.assertRaises(ValueError) as exception_context:
            self.table[3.14]
        self.assertEqual(exception_context.exception.args[0],
                         'Unsupported key type: float')

        with self.assertRaises(ValueError) as exception_context:
            self.table[b'name']
        self.assertEqual(exception_context.exception.args[0],
                         'Unsupported key type: {}'.format(binary_type_name))

    def test_table_getitem_column_doesnt_exist(self):
        with self.assertRaises(KeyError) as exception_context:
            self.table['doesnt-exist']

        self.assertEqual(exception_context.exception.args[0],
                         'doesnt-exist')

    def test_table_getitem_column_happy_path(self):
        expected_values = ['Álvaro Justen', 'Somebody', 'Douglas Adams']
        self.assertEqual(self.table['name'], expected_values)

        expected_values = [
                datetime.date(1987, 4, 29),
                datetime.date(1990, 2, 1),
                datetime.date(1952, 3, 11)]
        self.assertEqual(self.table['birthdate'], expected_values)

    def test_table_setitem_row(self):
        self.first_row['name'] = 'turicas'
        self.first_row['birthdate'] = datetime.date(2000, 1, 1)
        self.table[0] = self.first_row
        self.assertEqual(self.table[0].name, 'turicas')
        self.assertEqual(self.table[0].birthdate, datetime.date(2000, 1, 1))

    def test_field_names_and_types(self):
        self.assertEqual(self.table.field_names,
                         list(self.table.fields.keys()))
        self.assertEqual(self.table.field_types,
                         list(self.table.fields.values()))

    def test_table_setitem_column_happy_path_new_column(self):
        number_of_fields = len(self.table.fields)
        self.assertEqual(len(self.table), 3)

        self.table['user_id'] = [4, 5, 6]

        self.assertEqual(len(self.table), 3)
        self.assertEqual(len(self.table.fields), number_of_fields + 1)

        self.assertIn('user_id', self.table.fields)
        self.assertIs(self.table.fields['user_id'], rows.fields.IntegerField)
        self.assertEqual(self.table[0].user_id, 4)
        self.assertEqual(self.table[1].user_id, 5)
        self.assertEqual(self.table[2].user_id, 6)

    def test_table_setitem_column_happy_path_replace_column(self):
        number_of_fields = len(self.table.fields)
        self.assertEqual(len(self.table), 3)

        self.table['name'] = [4, 5, 6]  # change values *and* type

        self.assertEqual(len(self.table), 3)
        self.assertEqual(len(self.table.fields), number_of_fields)

        self.assertIn('name', self.table.fields)
        self.assertIs(self.table.fields['name'], rows.fields.IntegerField)
        self.assertEqual(self.table[0].name, 4)
        self.assertEqual(self.table[1].name, 5)
        self.assertEqual(self.table[2].name, 6)


    def test_table_setitem_column_slug_field_name(self):
        self.assertNotIn('user_id', self.table.fields)
        self.table['User ID'] = [4, 5, 6]
        self.assertIn('user_id', self.table.fields)

    def test_table_setitem_column_invalid_length(self):
        number_of_fields = len(self.table.fields)
        self.assertEqual(len(self.table), 3)

        with self.assertRaises(ValueError) as exception_context:
            self.table['user_id'] = [4, 5]  # list len should be 3

        self.assertEqual(len(self.table), 3)
        self.assertEqual(len(self.table.fields), number_of_fields)
        self.assertEqual(exception_context.exception.args[0],
                         'Values length (2) should be the same as Table '
                         'length (3)')

    def test_table_setitem_invalid_type(self):
        fields = self.table.fields.copy()
        self.assertEqual(len(self.table), 3)

        with self.assertRaises(ValueError) as exception_context:
            self.table[3.14] = []

        self.assertEqual(len(self.table), 3)  # should not add any row
        self.assertDictEqual(fields, self.table.fields)  # should not add field
        self.assertEqual(exception_context.exception.args[0],
                         'Unsupported key type: float')

        with self.assertRaises(ValueError) as exception_context:
            self.table[b'some_value'] = []

        self.assertEqual(len(self.table), 3)  # should not add any row
        self.assertDictEqual(fields, self.table.fields)  # should not add field
        self.assertEqual(exception_context.exception.args[0],
                         'Unsupported key type: {}'.format(binary_type_name))

    def test_table_delitem_row(self):
        table_rows = [row for row in self.table]
        before = len(self.table)
        del self.table[0]
        after = len(self.table)
        self.assertEqual(after, before - 1)
        for row, expected_row in zip(self.table, table_rows[1:]):
            self.assertEqual(row, expected_row)

    def test_table_delitem_column_doesnt_exist(self):
        with self.assertRaises(KeyError) as exception_context:
            del self.table['doesnt-exist']

        self.assertEqual(exception_context.exception.args[0],
                         'doesnt-exist')

    def test_table_delitem_column_happy_path(self):
        fields = self.table.fields.copy()
        self.assertEqual(len(self.table), 3)

        del self.table['name']

        self.assertEqual(len(self.table), 3)  # should not del any row
        self.assertEqual(len(self.table.fields), len(fields) - 1)

        self.assertDictEqual(dict(self.table[0]._asdict()),
                             {'birthdate': datetime.date(1987, 4, 29)})
        self.assertDictEqual(dict(self.table[1]._asdict()),
                             {'birthdate': datetime.date(1990, 2, 1)})
        self.assertDictEqual(dict(self.table[2]._asdict()),
                             {'birthdate': datetime.date(1952, 3, 11)})

    def test_table_delitem_column_invalid_type(self):
        fields = self.table.fields.copy()
        self.assertEqual(len(self.table), 3)

        with self.assertRaises(ValueError) as exception_context:
            del self.table[3.14]

        self.assertEqual(len(self.table), 3)  # should not del any row
        self.assertDictEqual(fields, self.table.fields)  # should not del field
        self.assertEqual(exception_context.exception.args[0],
                         'Unsupported key type: float')

        with self.assertRaises(ValueError) as exception_context:
            self.table[b'name'] = []  # 'name' actually exists

        self.assertEqual(len(self.table), 3)  # should not del any row
        self.assertDictEqual(fields, self.table.fields)  # should not del field
        self.assertEqual(exception_context.exception.args[0],
                         'Unsupported key type: {}'.format(binary_type_name))

    def test_table_add(self):
        self.assertIs(self.table + 0, self.table)
        self.assertIs(0 + self.table, self.table)

        new_table = self.table + self.table
        self.assertEqual(new_table.fields, self.table.fields)
        self.assertEqual(len(new_table), 2 * len(self.table))
        self.assertEqual(list(new_table), list(self.table) * 2)

    def test_table_add_error(self):
        with self.assertRaises(ValueError):
            self.table + 1
        with self.assertRaises(ValueError):
            1 + self.table

    def test_table_order_by(self):
        with self.assertRaises(ValueError):
            self.table.order_by('doesnt_exist')

        before = [row.birthdate for row in self.table]
        self.table.order_by('birthdate')
        after = [row.birthdate for row in self.table]
        self.assertNotEqual(before, after)
        self.assertEqual(sorted(before), after)

        self.table.order_by('-birthdate')
        final = [row.birthdate for row in self.table]
        self.assertEqual(final, list(reversed(after)))

        self.table.order_by('name')
        expected_rows = [
            {'name': 'Douglas Adams', 'birthdate': datetime.date(1952, 3, 11)},
            {'name': 'Somebody', 'birthdate': datetime.date(1990, 2, 1)},
            {'name': 'Álvaro Justen', 'birthdate': datetime.date(1987, 4, 29)}]
        for expected_row, row in zip(expected_rows, self.table):
            self.assertEqual(expected_row, dict(row._asdict()))

    def test_table_repr(self):
        expected = '<rows.Table 2 fields, 3 rows>'
        self.assertEqual(expected, repr(self.table))

    def test_table_add_time(self):
        '''rows.Table.__add__ should be constant time

        To test it we double table size for each round and then compare the
        standard deviation to the mean (it will be almost the mean if the
        algorithm is not fast enough and almost 10% of the mean if it's good).
        '''
        rounds = []
        table = utils.table
        for _ in range(10):
            start = time.time()
            table = table + table
            end = time.time()
            rounds.append(end - start)

        mean = sum(rounds) / len(rounds)
        stdev = math.sqrt((1.0 / (len(rounds) - 1)) *
                          sum((value - mean) ** 2 for value in rounds))
        self.assertTrue(0.2 * mean > stdev)