Repository: quantopian/zipline
File: tests/pipeline/test_column.py (Python)

Code before:
        result = self.engine.run_pipeline(
            pipe,
            dates_to_test[0],
            dates_to_test[-1],
        )
        for column in columns:
            with ignore_pandas_nan_categorical_warning():
                col_result = result[column.name].unstack()

            expected_col_result = self.expected_latest(column, cal_slice)
            assert_frame_equal(col_result, expected_col_result)

    @parameterized.expand([
        (operator.gt,),
        (operator.ge,),
        (operator.lt,),
        (operator.le,),
    ])
    def test_comparison_errors(self, compare):
        columns = TDS.columns
        for column in columns:
            with self.assertRaises(BoundColumnInvalidCompare):
                compare(column, 1000)

            with self.assertRaises(BoundColumnInvalidCompare):
                compare(column, 'test')


Review comment (bug):
These are good tests; but I think it's worth also testing the specific error message they produce. You can probably just replace `assertRaises` with `assertRaisesRegexp`: https://docs.python.org/2/library/unittest.html#unittest.TestCase.assertRaisesRegexp

Testing the message will ensure that we know exactly how `other.__class__` gets rendered -- maybe `{other.__class__.__name__}` would be better? Maybe `{other.__class__} instance` would be more readable? You may have already experimented with variations in the REPL, but you can save future readers from having to do the same.

Testing the message also helps avoid a very common error, which I don't _think_ you've made here, but a future editor of your code might add. Can you spot the bug below?

```python
msg = (
    "Can't compare {column!s} with {other.__class__}.  Did you mean"
    "to append .latest?"
)
```


Code after:
        result = self.engine.run_pipeline(
            pipe,
            dates_to_test[0],
            dates_to_test[-1],
        )
        for column in columns:
            with ignore_pandas_nan_categorical_warning():
                col_result = result[column.name].unstack()

            expected_col_result = self.expected_latest(column, cal_slice)
            assert_frame_equal(col_result, expected_col_result)

    @parameterized.expand([
        (operator.gt,),
        (operator.ge,),
        (operator.lt,),
        (operator.le,),
    ])
    def test_comparison_errors(self, op):
        for column in TDS.columns:
            with self.assertRaises(TypeError):
                op(column, 1000)
            with self.assertRaises(TypeError):
                op(1000, column)
            with self.assertRaises(TypeError):
                op(column, 'test')
            with self.assertRaises(TypeError):
                op('test', column)

    def test_comparison_error_message(self):
        column = USEquityPricing.volume
        err_msg = (
            "Can't compare 'EquityPricing<US>.volume' with 'int'."
            " (Did you mean to use '.latest'?)"
        )

        with self.assertRaises(TypeError) as e:
            column < 1000
        self.assertEqual(str(e.exception), err_msg)

        try:
            column.latest < 1000
        except TypeError:
            self.fail()