class TestIndexedPieceA(TestCase):
    """The 'A' part of tests for IndexedPiece."""
    def setUp(self):
        """Set up some stuff."""
        self._pathname = 'test_path'
        self.ind_piece = IndexedPiece(self._pathname)

    def test_metadata(self):
        """access fields that are set by default"""
        pathname = self.ind_piece.metadata('pathname')
        self.assertEquals(self._pathname, pathname, "pathname has changed!")
        # assign a value to a valid field
        self.ind_piece.metadata('date', 2)
        value = self.ind_piece.metadata('date')
        self.assertEquals(
            2, value, "extracted metadata field doesn't match assigned value")
        # assign a value to an invalid field
        self.assertRaises(AttributeError, self.ind_piece.metadata, 'field', 2)
        # access an invalid value
        self.assertRaises(AttributeError, self.ind_piece.metadata,
                          'invalid_field')
        # try accessing keys with invalid types
        self.assertRaises(TypeError, self.ind_piece.metadata, 2)
        self.assertRaises(TypeError, self.ind_piece.metadata, [])
        self.assertRaises(TypeError, self.ind_piece.metadata, {})

    def test_get_data_0(self):
        """try getting data for a non-Indexer, non-Experimenter class"""
        non_analyzer = Mock()
        self.assertRaises(KeyError, self.ind_piece.get_data, non_analyzer)

    def test_get_data_1(self):
        """
        That get_data() complains when an Indexer expects the results of another Indexer but
        doesn't get them.
        """
        mock_indexer_cls = type('MockIndexer', (Indexer, ), {})
        mock_indexer_cls.required_score_type = pandas.DataFrame
        self.assertRaises(RuntimeWarning, self.ind_piece.get_data,
                          vis.analyzers.indexers.ngram.NGramIndexer)

    def test_get_data_2(self):
        """
        That get_data() complains when you call it with something that isn't either an Indexer
        or Experimenter.
        """
        self.assertRaises(KeyError, self.ind_piece.get_data, TestIndexedPieceA)

    def test_get_nrindex_1(self):
        """That _get_noterest() returns self._analyses['noterest'] if it's not None."""
        # pylint: disable=W0212
        self.ind_piece._analyses['noterest'] = 42
        self.assertEqual(42, self.ind_piece._get_noterest())

    def test_str_1(self):
        """__str__() without having imported yet"""
        # NB: adjusting _imported is the whole point of the test
        # pylint: disable=W0212
        self.ind_piece._imported = False
        with patch(
                'vis.models.indexed_piece.IndexedPiece.metadata') as mock_meta:
            mock_meta.return_value = '42'
            expected = '<IndexedPiece (42)>'
            actual = self.ind_piece.__str__()
            self.assertEqual(expected, actual)
            mock_meta.assert_called_once_with('pathname')

    def test_str_2(self):
        """__str__() with proper title and composer"""
        # NB: adjusting _imported is the whole point of the test
        # pylint: disable=W0212
        self.ind_piece._imported = True
        with patch(
                'vis.models.indexed_piece.IndexedPiece.metadata') as mock_meta:
            returns = ['some ridiculous piece', 'a no-name composer']

            def side_effect(*args):
                # NB: we need to accept "args" as a mock framework formality
                # pylint: disable=W0613
                return returns.pop(0)

            mock_meta.side_effect = side_effect
            expected = '<IndexedPiece (some ridiculous piece by a no-name composer)>'
            actual = self.ind_piece.__str__()
            self.assertEqual(expected, actual)
            expected_calls = [call('title'), call('composer')]
            self.assertSequenceEqual(expected_calls, mock_meta.call_args_list)
class TestIndexedPieceA(TestCase):
    """The 'A' part of tests for IndexedPiece."""

    def setUp(self):
        """Set up some stuff."""
        self._pathname = 'test_path'
        self.ind_piece = IndexedPiece(self._pathname)

    def test_metadata(self):
        """access fields that are set by default"""
        pathname = self.ind_piece.metadata('pathname')
        self.assertEquals(self._pathname, pathname, "pathname has changed!")
        # assign a value to a valid field
        self.ind_piece.metadata('date', 2)
        value = self.ind_piece.metadata('date')
        self.assertEquals(2, value, "extracted metadata field doesn't match assigned value")
        # assign a value to an invalid field
        self.assertRaises(AttributeError, self.ind_piece.metadata, 'field', 2)
        # access an invalid value
        self.assertRaises(AttributeError, self.ind_piece.metadata, 'invalid_field')
        # try accessing keys with invalid types
        self.assertRaises(TypeError, self.ind_piece.metadata, 2)
        self.assertRaises(TypeError, self.ind_piece.metadata, [])
        self.assertRaises(TypeError, self.ind_piece.metadata, {})

    def test_get_data_0(self):
        """try getting data for a non-Indexer, non-Experimenter class"""
        non_analyzer = Mock()
        self.assertRaises(KeyError, self.ind_piece.get_data, non_analyzer)

    def test_get_data_1(self):
        """
        That get_data() complains when an Indexer expects the results of another Indexer but
        doesn't get them.
        """
        mock_indexer_cls = type('MockIndexer', (Indexer,), {})
        mock_indexer_cls.required_score_type = pandas.DataFrame
        self.assertRaises(RuntimeWarning, self.ind_piece.get_data, vis.analyzers.indexers.ngram.NGramIndexer)

    def test_get_data_2(self):
        """
        That get_data() complains when you call it with something that isn't either an Indexer
        or Experimenter.
        """
        self.assertRaises(KeyError, self.ind_piece.get_data, TestIndexedPieceA)

    def test_get_nrindex_1(self):
        """That _get_noterest() returns self._analyses['noterest'] if it's not None."""
        # pylint: disable=W0212
        self.ind_piece._analyses['noterest'] = 42
        self.assertEqual(42, self.ind_piece._get_noterest())

    def test_str_1(self):
        """__str__() without having imported yet"""
        # NB: adjusting _imported is the whole point of the test
        # pylint: disable=W0212
        self.ind_piece._imported = False
        with patch('vis.models.indexed_piece.IndexedPiece.metadata') as mock_meta:
            mock_meta.return_value = '42'
            expected = '<IndexedPiece (42)>'
            actual = self.ind_piece.__str__()
            self.assertEqual(expected, actual)
            mock_meta.assert_called_once_with('pathname')

    def test_str_2(self):
        """__str__() with proper title and composer"""
        # NB: adjusting _imported is the whole point of the test
        # pylint: disable=W0212
        self.ind_piece._imported = True
        with patch('vis.models.indexed_piece.IndexedPiece.metadata') as mock_meta:
            returns = ['some ridiculous piece', 'a no-name composer']
            def side_effect(*args):
                # NB: we need to accept "args" as a mock framework formality
                # pylint: disable=W0613
                return returns.pop(0)
            mock_meta.side_effect = side_effect
            expected = '<IndexedPiece (some ridiculous piece by a no-name composer)>'
            actual = self.ind_piece.__str__()
            self.assertEqual(expected, actual)
            expected_calls = [call('title'), call('composer')]
            self.assertSequenceEqual(expected_calls, mock_meta.call_args_list)