コード例 #1
0
 def test_object_caching(self):
     # Creating a Feature with the same name as an existing
     # Feature must return the existing Feature, if both are
     # associated with the same BinaryFeaturesModel.
     feature1 = BaseFeature(self.bfm, 'voiced')
     feature2 = BaseFeature(self.bfm, 'voiced')
     self.assertEqual(feature1, feature2)
     feature3 = BaseFeature(self.bfm, 'consonantal')
     self.assertNotEqual(feature1, feature3)
     bfm2 = BinaryFeaturesModel()
     feature4 = BaseFeature(bfm2, 'voiced')
     self.assertNotEqual(feature1, feature4)
     # It is an error to create a Feature with the same IPA form
     # but of a different type (subclass).
     self.assertRaises(InvalidFeatureError, SuprasegmentalFeature, self.bfm,
                       'voiced')
     # Initialisation of a Feature should happen only once.
     character1 = BaseCharacter(self.bfm, 'a')
     character1.set_feature_value(feature1, HAS_FEATURE)
     self.assertEqual(feature1.get_value_characters(HAS_FEATURE),
                      set([character1]))
     feature5 = BaseFeature(self.bfm, 'voiced')
     self.assertEqual(feature1.get_value_characters(HAS_FEATURE),
                      set([character1]))
     feature6 = SuprasegmentalFeature(self.bfm, 'syllabic')
     character2 = SuprasegmentalCharacter(self.bfm, 'b')
     character2.set_feature_value(feature6, HAS_FEATURE)
     self.assertEqual(feature6.get_value_characters(HAS_FEATURE),
                      set([character2]))
     feature7 = SuprasegmentalFeature(self.bfm, 'syllabic')
     self.assertEqual(feature6.get_value_characters(HAS_FEATURE),
                      set([character2]))
コード例 #2
0
ファイル: feature_tests.py プロジェクト: ajenhl/zounds
 def test_object_caching (self):
     # Creating a Feature with the same name as an existing
     # Feature must return the existing Feature, if both are
     # associated with the same BinaryFeaturesModel.
     feature1 = BaseFeature(self.bfm, 'voiced')
     feature2 = BaseFeature(self.bfm, 'voiced')
     self.assertEqual(feature1, feature2)
     feature3 = BaseFeature(self.bfm, 'consonantal')
     self.assertNotEqual(feature1, feature3)
     bfm2 = BinaryFeaturesModel()
     feature4 = BaseFeature(bfm2, 'voiced')
     self.assertNotEqual(feature1, feature4)
     # It is an error to create a Feature with the same IPA form
     # but of a different type (subclass).
     self.assertRaises(InvalidFeatureError, SuprasegmentalFeature, self.bfm,
                       'voiced')
     # Initialisation of a Feature should happen only once.
     character1 = BaseCharacter(self.bfm, 'a')
     character1.set_feature_value(feature1, HAS_FEATURE)
     self.assertEqual(feature1.get_value_characters(HAS_FEATURE),
                      set([character1]))
     feature5 = BaseFeature(self.bfm, 'voiced')
     self.assertEqual(feature1.get_value_characters(HAS_FEATURE),
                      set([character1]))
     feature6 = SuprasegmentalFeature(self.bfm, 'syllabic')
     character2 = SuprasegmentalCharacter(self.bfm, 'b')
     character2.set_feature_value(feature6, HAS_FEATURE)
     self.assertEqual(feature6.get_value_characters(HAS_FEATURE),
                      set([character2]))
     feature7 = SuprasegmentalFeature(self.bfm, 'syllabic')
     self.assertEqual(feature6.get_value_characters(HAS_FEATURE),
                      set([character2]))
コード例 #3
0
 def test_feature_value(self):
     character = SuprasegmentalCharacter(self.bfm, 'a')
     feature = SuprasegmentalFeature(self.bfm, 'voiced')
     character.set_feature_value(feature, HAS_FEATURE)
     value = character.get_feature_value(feature)
     self.assertEqual(value, HAS_FEATURE)
     character.set_feature_value(feature, NOT_HAS_FEATURE)
     value = character.get_feature_value(feature)
     self.assertEqual(value, NOT_HAS_FEATURE)
コード例 #4
0
 def test_feature_value (self):
     character = SuprasegmentalCharacter(self.bfm, 'a')
     feature = SuprasegmentalFeature(self.bfm, 'voiced')
     character.set_feature_value(feature, HAS_FEATURE)
     value = character.get_feature_value(feature)
     self.assertEqual(value, HAS_FEATURE)
     character.set_feature_value(feature, NOT_HAS_FEATURE)
     value = character.get_feature_value(feature)
     self.assertEqual(value, NOT_HAS_FEATURE)
コード例 #5
0
 def test_delete(self):
     Feature._cache = {}
     self.assertEqual(len(Feature._cache), 0)
     feature = SuprasegmentalFeature(self.bfm, 'voiced')
     character = SuprasegmentalCharacter(self.bfm, 'a')
     character.set_feature_value(feature, HAS_FEATURE)
     self.assertEqual(len(Feature._cache), 1)
     self.assertEqual(character.get_feature_value(feature), HAS_FEATURE)
     feature.delete()
     self.assertEqual(len(Feature._cache), 0)
     self.assertRaises(MismatchedModelsError, character.get_feature_value,
                       feature)
コード例 #6
0
 def test_delete (self):
     Feature._cache = {}
     self.assertEqual(len(Feature._cache), 0)
     feature = SuprasegmentalFeature(self.bfm, 'voiced')
     character = SuprasegmentalCharacter(self.bfm, 'a')
     character.set_feature_value(feature, HAS_FEATURE)
     self.assertEqual(len(Feature._cache), 1)
     self.assertEqual(character.get_feature_value(feature), HAS_FEATURE)
     feature.delete()
     self.assertEqual(len(Feature._cache), 0)
     self.assertRaises(MismatchedModelsError, character.get_feature_value,
                       feature)
コード例 #7
0
ファイル: cluster_tests.py プロジェクト: ajenhl/zounds
 def test_normalised_form_cluster_creation (self):
     # Test that the correct subclass of Cluster is created from a
     # normalised form.
     bfm = BinaryFeaturesModel()
     feature1 = BaseFeature(bfm, 'anterior')
     feature2 = SuprasegmentalFeature(bfm, 'long')
     character1 = BaseCharacter(bfm, 'a')
     character1.set_feature_value(feature1, HAS_FEATURE)
     character2 = SuprasegmentalCharacter(bfm, 'b')
     character2.set_feature_value(feature2, HAS_FEATURE)
     nf1 = NormalisedForm('{}{}'.format(BNFM, HAS_FEATURE))
     nf2 = NormalisedForm('{}{}'.format(SNFM, HAS_FEATURE))
     cluster1 = Cluster(bfm, normalised_form=nf1)
     cluster2 = Cluster(bfm, normalised_form=nf2)
     self.assertTrue(isinstance(cluster1, BaseCluster))
     self.assertTrue(isinstance(cluster2, SuprasegmentalCluster))
     self.assertRaises(IllegalArgumentError, Cluster, '')
コード例 #8
0
 def test_normalised_form_cluster_creation(self):
     # Test that the correct subclass of Cluster is created from a
     # normalised form.
     bfm = BinaryFeaturesModel()
     feature1 = BaseFeature(bfm, 'anterior')
     feature2 = SuprasegmentalFeature(bfm, 'long')
     character1 = BaseCharacter(bfm, 'a')
     character1.set_feature_value(feature1, HAS_FEATURE)
     character2 = SuprasegmentalCharacter(bfm, 'b')
     character2.set_feature_value(feature2, HAS_FEATURE)
     nf1 = NormalisedForm('{}{}'.format(BNFM, HAS_FEATURE))
     nf2 = NormalisedForm('{}{}'.format(SNFM, HAS_FEATURE))
     cluster1 = Cluster(bfm, normalised_form=nf1)
     cluster2 = Cluster(bfm, normalised_form=nf2)
     self.assertTrue(isinstance(cluster1, BaseCluster))
     self.assertTrue(isinstance(cluster2, SuprasegmentalCluster))
     self.assertRaises(IllegalArgumentError, Cluster, '')
コード例 #9
0
 def test_normalised_form(self):
     feature1 = SuprasegmentalFeature(self.bfm, 'anterior')
     character = SuprasegmentalCharacter(self.bfm, 'n')
     character.set_feature_value(feature1, HAS_FEATURE)
     self.assertEqual(character.normalised_form,
                      NormalisedForm('{0}{1}'.format(SNFM, HAS_FEATURE)))
     # Adding a feature changes the normalised form.
     feature2 = SuprasegmentalFeature(self.bfm, 'dental')
     # All features must have a value.
     self.assertRaises(InvalidCharacterError, getattr, character,
                       'normalised_form')
     character.set_feature_value(feature2, NOT_HAS_FEATURE)
     self.assertEqual(
         character.normalised_form,
         NormalisedForm('{0}{1}{2}'.format(SNFM, HAS_FEATURE,
                                           NOT_HAS_FEATURE)))
     # The order of the normalised form feature values is
     # alphabetical by feature name.
     feature3 = SuprasegmentalFeature(self.bfm, 'consonantal')
     character.set_feature_value(feature3, HAS_FEATURE)
     self.assertEqual(
         character.normalised_form,
         NormalisedForm('{0}{1}{1}{2}'.format(SNFM, HAS_FEATURE,
                                              NOT_HAS_FEATURE)))
     # Renaming a feature may change the normalised form.
     feature3.name = 'vocalic'
     self.assertEqual(
         character.normalised_form,
         NormalisedForm('{0}{1}{2}{1}'.format(SNFM, HAS_FEATURE,
                                              NOT_HAS_FEATURE)))
     # Changing a feature value changes the normalised form.
     character.set_feature_value(feature1, INAPPLICABLE_FEATURE)
     self.assertEqual(
         character.normalised_form,
         NormalisedForm('{0}{3}{2}{1}'.format(SNFM, HAS_FEATURE,
                                              NOT_HAS_FEATURE,
                                              INAPPLICABLE_FEATURE)))
     # Removing a feature value changes the normalised form.
     feature3.delete()
     self.assertEqual(
         character.normalised_form,
         NormalisedForm('{0}{2}{1}'.format(SNFM, NOT_HAS_FEATURE,
                                           INAPPLICABLE_FEATURE)))
     # Adding a feature of a different type does not change the
     # normalised form.
     feature4 = BaseFeature(self.bfm, 'syllabic')
     self.assertEqual(
         character.normalised_form,
         NormalisedForm('{0}{2}{1}'.format(SNFM, NOT_HAS_FEATURE,
                                           INAPPLICABLE_FEATURE)))
コード例 #10
0
ファイル: character_tests.py プロジェクト: ajenhl/zounds
 def test_object_caching (self):
     # Creating a Character with the same IPA form as an existing
     # Character must return the existing Character, if both are
     # associated with the same BinaryFeaturesModel.
     character1 = BaseCharacter(self.bfm, 'a')
     character2 = BaseCharacter(self.bfm, 'a')
     self.assertEqual(character1, character2)
     character3 = BaseCharacter(self.bfm, 'b')
     self.assertNotEqual(character1, character3)
     bfm2 = BinaryFeaturesModel()
     character4 = BaseCharacter(bfm2, 'a')
     self.assertNotEqual(character1, character4)
     # It is an error to create a Character with the same IPA form
     # but of a different type (subclass).
     self.assertRaises(InvalidCharacterError, DiacriticCharacter,
                       self.bfm, 'a')
     # Initialising of the Character should happen only once.
     feature = BaseFeature(self.bfm, 'voiced')
     character1.set_feature_value(feature, HAS_FEATURE)
     self.assertEqual(character1.get_feature_value(feature), HAS_FEATURE)
     character5 = BaseCharacter(self.bfm, 'a')
     self.assertEqual(character1.get_feature_value(feature), HAS_FEATURE)
     character6 = DiacriticCharacter(self.bfm, 'c')
     character6.set_feature_value(feature, HAS_FEATURE)
     self.assertEqual(character6.get_feature_value(feature), HAS_FEATURE)
     character7 = DiacriticCharacter(self.bfm, 'c')
     self.assertEqual(character6.get_feature_value(feature), HAS_FEATURE)
     character8 = SpacingCharacter(self.bfm, 'd')
     character8.set_feature_value(feature, HAS_FEATURE)
     self.assertEqual(character8.get_feature_value(feature), HAS_FEATURE)
     character9 = SpacingCharacter(self.bfm, 'd')
     self.assertEqual(character8.get_feature_value(feature), HAS_FEATURE)
     character10 = SuprasegmentalCharacter(self.bfm, 'e')
     feature2 = SuprasegmentalFeature(self.bfm, 'syllabic')
     character10.set_feature_value(feature2, HAS_FEATURE)
     self.assertEqual(character10.get_feature_value(feature2), HAS_FEATURE)
     character11 = SuprasegmentalCharacter(self.bfm, 'e')
     self.assertEqual(character10.get_feature_value(feature2), HAS_FEATURE)
コード例 #11
0
ファイル: character_tests.py プロジェクト: Anaphory/zounds
 def test_object_caching(self):
     # Creating a Character with the same IPA form as an existing
     # Character must return the existing Character, if both are
     # associated with the same BinaryFeaturesModel.
     character1 = BaseCharacter(self.bfm, 'a')
     character2 = BaseCharacter(self.bfm, 'a')
     self.assertEqual(character1, character2)
     character3 = BaseCharacter(self.bfm, 'b')
     self.assertNotEqual(character1, character3)
     bfm2 = BinaryFeaturesModel()
     character4 = BaseCharacter(bfm2, 'a')
     self.assertNotEqual(character1, character4)
     # It is an error to create a Character with the same IPA form
     # but of a different type (subclass).
     self.assertRaises(InvalidCharacterError, DiacriticCharacter, self.bfm,
                       'a')
     # Initialising of the Character should happen only once.
     feature = BaseFeature(self.bfm, 'voiced')
     character1.set_feature_value(feature, HAS_FEATURE)
     self.assertEqual(character1.get_feature_value(feature), HAS_FEATURE)
     character5 = BaseCharacter(self.bfm, 'a')
     self.assertEqual(character1.get_feature_value(feature), HAS_FEATURE)
     character6 = DiacriticCharacter(self.bfm, 'c')
     character6.set_feature_value(feature, HAS_FEATURE)
     self.assertEqual(character6.get_feature_value(feature), HAS_FEATURE)
     character7 = DiacriticCharacter(self.bfm, 'c')
     self.assertEqual(character6.get_feature_value(feature), HAS_FEATURE)
     character8 = SpacingCharacter(self.bfm, 'd')
     character8.set_feature_value(feature, HAS_FEATURE)
     self.assertEqual(character8.get_feature_value(feature), HAS_FEATURE)
     character9 = SpacingCharacter(self.bfm, 'd')
     self.assertEqual(character8.get_feature_value(feature), HAS_FEATURE)
     character10 = SuprasegmentalCharacter(self.bfm, 'e')
     feature2 = SuprasegmentalFeature(self.bfm, 'syllabic')
     character10.set_feature_value(feature2, HAS_FEATURE)
     self.assertEqual(character10.get_feature_value(feature2), HAS_FEATURE)
     character11 = SuprasegmentalCharacter(self.bfm, 'e')
     self.assertEqual(character10.get_feature_value(feature2), HAS_FEATURE)
コード例 #12
0
 def test_normalised_form (self):
     feature1 = SuprasegmentalFeature(self.bfm, 'anterior')
     character = SuprasegmentalCharacter(self.bfm, 'n')
     character.set_feature_value(feature1, HAS_FEATURE)
     self.assertEqual(character.normalised_form, NormalisedForm(
             '{0}{1}'.format(SNFM, HAS_FEATURE)))
     # Adding a feature changes the normalised form.
     feature2 = SuprasegmentalFeature(self.bfm, 'dental')
     # All features must have a value.
     self.assertRaises(InvalidCharacterError, getattr, character,
                       'normalised_form')
     character.set_feature_value(feature2, NOT_HAS_FEATURE)
     self.assertEqual(character.normalised_form, NormalisedForm(
             '{0}{1}{2}'.format(SNFM, HAS_FEATURE, NOT_HAS_FEATURE)))
     # The order of the normalised form feature values is
     # alphabetical by feature name.
     feature3 = SuprasegmentalFeature(self.bfm, 'consonantal')
     character.set_feature_value(feature3, HAS_FEATURE)
     self.assertEqual(character.normalised_form, NormalisedForm(
             '{0}{1}{1}{2}'.format(SNFM, HAS_FEATURE, NOT_HAS_FEATURE)))
     # Renaming a feature may change the normalised form.
     feature3.name = 'vocalic'
     self.assertEqual(character.normalised_form, NormalisedForm(
             '{0}{1}{2}{1}'.format(SNFM, HAS_FEATURE, NOT_HAS_FEATURE)))
     # Changing a feature value changes the normalised form.
     character.set_feature_value(feature1, INAPPLICABLE_FEATURE)
     self.assertEqual(character.normalised_form, NormalisedForm(
             '{0}{3}{2}{1}'.format(SNFM, HAS_FEATURE, NOT_HAS_FEATURE,
                                   INAPPLICABLE_FEATURE)))
     # Removing a feature value changes the normalised form.
     feature3.delete()
     self.assertEqual(character.normalised_form, NormalisedForm(
             '{0}{2}{1}'.format(SNFM, NOT_HAS_FEATURE,
                                INAPPLICABLE_FEATURE)))
     # Adding a feature of a different type does not change the
     # normalised form.
     feature4 = BaseFeature(self.bfm, 'syllabic')
     self.assertEqual(character.normalised_form, NormalisedForm(
             '{0}{2}{1}'.format(SNFM, NOT_HAS_FEATURE,
                                INAPPLICABLE_FEATURE)))
コード例 #13
0
 def test_value_characters(self):
     feature = SuprasegmentalFeature(self.bfm, 'voiced')
     self.assertEqual(feature.get_value_characters(HAS_FEATURE), set())
     self.assertEqual(feature.get_value_characters(NOT_HAS_FEATURE), set())
     character = SuprasegmentalCharacter(self.bfm, 'a')
     character.set_feature_value(feature, HAS_FEATURE)
     self.assertEqual(feature.get_value_characters(HAS_FEATURE),
                      set([character]))
     self.assertEqual(feature.get_value_characters(NOT_HAS_FEATURE), set())
     character.set_feature_value(feature, NOT_HAS_FEATURE)
     self.assertEqual(feature.get_value_characters(HAS_FEATURE), set())
     self.assertEqual(feature.get_value_characters(NOT_HAS_FEATURE),
                      set([character]))
     character.set_feature_value(feature, INAPPLICABLE_FEATURE)
     self.assertEqual(feature.get_value_characters(HAS_FEATURE), set())
     self.assertEqual(feature.get_value_characters(NOT_HAS_FEATURE), set())
コード例 #14
0
 def test_value_characters (self):
     feature = SuprasegmentalFeature(self.bfm, 'voiced')
     self.assertEqual(feature.get_value_characters(HAS_FEATURE), set())
     self.assertEqual(feature.get_value_characters(NOT_HAS_FEATURE), set())
     character = SuprasegmentalCharacter(self.bfm, 'a')
     character.set_feature_value(feature, HAS_FEATURE)
     self.assertEqual(feature.get_value_characters(HAS_FEATURE),
                      set([character]))
     self.assertEqual(feature.get_value_characters(NOT_HAS_FEATURE), set())
     character.set_feature_value(feature, NOT_HAS_FEATURE)
     self.assertEqual(feature.get_value_characters(HAS_FEATURE), set())
     self.assertEqual(feature.get_value_characters(NOT_HAS_FEATURE),
                      set([character]))
     character.set_feature_value(feature, INAPPLICABLE_FEATURE)
     self.assertEqual(feature.get_value_characters(HAS_FEATURE), set())
     self.assertEqual(feature.get_value_characters(NOT_HAS_FEATURE), set())
コード例 #15
0
class ClusterTestCase(unittest.TestCase):
    def setUp(self):
        self.bfm = BinaryFeaturesModel()
        self.phrase = SuprasegmentalFeature(self.bfm, 'phrase')
        self.stressed = SuprasegmentalFeature(self.bfm, 'stressed')
        self.syllabic = SuprasegmentalFeature(self.bfm, 'syllabic')
        self.a = SuprasegmentalCharacter(self.bfm, 'a')
        self.a.set_feature_value(self.phrase, HAS_FEATURE)
        self.a.set_feature_value(self.stressed, INAPPLICABLE_FEATURE)
        self.a.set_feature_value(self.syllabic, NOT_HAS_FEATURE)
        self.b = SuprasegmentalCharacter(self.bfm, 'b')
        self.b.set_feature_value(self.phrase, INAPPLICABLE_FEATURE)
        self.b.set_feature_value(self.stressed, NOT_HAS_FEATURE)
        self.b.set_feature_value(self.syllabic, INAPPLICABLE_FEATURE)

    def test_applier_form(self):
        cluster1 = SuprasegmentalCluster(self.bfm,
                                         suprasegmental_characters=[self.a])
        af1 = '{0}{1}{2}{3}{4}'.format(AFM, SNFM, HAS_FEATURE,
                                       INAPPLICABLE_FEATURE, NOT_HAS_FEATURE)
        self.assertEqual(cluster1.applier_form, af1)
        cluster2 = SuprasegmentalCluster(
            self.bfm, suprasegmental_characters=[self.a, self.b])
        af2 = '{0}{1}{2}{3}{3}'.format(AFM, SNFM, HAS_FEATURE, NOT_HAS_FEATURE)
        self.assertEqual(cluster2.applier_form, af2)

    def test_normalised_form(self):
        cluster1 = SuprasegmentalCluster(self.bfm,
                                         suprasegmental_characters=[self.a])
        nf1 = NormalisedForm('{0}{1}{2}{3}'.format(SNFM, HAS_FEATURE,
                                                   INAPPLICABLE_FEATURE,
                                                   NOT_HAS_FEATURE))
        self.assertEqual(cluster1.normalised_form, nf1)
        cluster2 = SuprasegmentalCluster(
            self.bfm, suprasegmental_characters=[self.a, self.b])
        nf2 = NormalisedForm('{0}{1}{2}{2}'.format(SNFM, HAS_FEATURE,
                                                   NOT_HAS_FEATURE))
        self.assertEqual(cluster2.normalised_form, nf2)
        cluster3 = Cluster(self.bfm, normalised_form=nf2)
        self.assertEqual(cluster3.normalised_form, nf2)

    def test_string_form(self):
        cluster1 = SuprasegmentalCluster(self.bfm,
                                         suprasegmental_characters=[self.a])
        self.assertEqual(str(cluster1), 'a')
        cluster2 = SuprasegmentalCluster(
            self.bfm, suprasegmental_characters=[self.a, self.b])
        self.assertEqual(str(cluster2), 'ab')
        cluster3 = SuprasegmentalCluster(
            self.bfm, suprasegmental_characters=[self.b, self.a])
        self.assertEqual(str(cluster3), 'ba')

    def test_suprasegmental_cluster_creation_illegal(self):
        bfm1 = BinaryFeaturesModel()
        bfm2 = BinaryFeaturesModel()
        character1 = BaseCharacter(bfm1, 'a')
        character3 = SuprasegmentalCharacter(bfm1, 'b')
        character4 = SuprasegmentalCharacter(bfm2, 'c')
        nf1 = NormalisedForm('{}{}'.format(SNFM, HAS_FEATURE))
        # A SuprasegmentalCluster must be initialised with at least
        # one suprasegmental character or a normalised form.
        self.assertRaises(IllegalArgumentError, SuprasegmentalCluster, bfm1)
        # A SuprasegmentalCluster must not be initialised with both
        # suprasegmental characters and a normalised form.
        self.assertRaises(IllegalArgumentError,
                          SuprasegmentalCluster,
                          bfm1,
                          suprasegmental_characters=[character3],
                          normalised_form=nf1)
        # All of the characters in a cluster must be associated with
        # the same binary features model.
        self.assertRaises(MismatchedModelsError,
                          SuprasegmentalCluster,
                          bfm1,
                          suprasegmental_characters=[character4])
        # All of the characters in a cluster must be suprasegmental.
        self.assertRaises(MismatchedTypesError,
                          SuprasegmentalCluster,
                          bfm1,
                          suprasegmental_characters=[character1, character3])
コード例 #16
0
class ClusterTestCase (unittest.TestCase):

    def setUp (self):
        self.bfm = BinaryFeaturesModel()
        self.phrase = SuprasegmentalFeature(self.bfm, 'phrase')
        self.stressed = SuprasegmentalFeature(self.bfm, 'stressed')
        self.syllabic = SuprasegmentalFeature(self.bfm, 'syllabic')
        self.a = SuprasegmentalCharacter(self.bfm, 'a')
        self.a.set_feature_value(self.phrase, HAS_FEATURE)
        self.a.set_feature_value(self.stressed, INAPPLICABLE_FEATURE)
        self.a.set_feature_value(self.syllabic, NOT_HAS_FEATURE)
        self.b = SuprasegmentalCharacter(self.bfm, 'b')
        self.b.set_feature_value(self.phrase, INAPPLICABLE_FEATURE)
        self.b.set_feature_value(self.stressed, NOT_HAS_FEATURE)
        self.b.set_feature_value(self.syllabic, INAPPLICABLE_FEATURE)

    def test_applier_form (self):
        cluster1 = SuprasegmentalCluster(self.bfm, suprasegmental_characters=
                                         [self.a])
        af1 = '{0}{1}{2}{3}{4}'.format(AFM, SNFM, HAS_FEATURE,
                                       INAPPLICABLE_FEATURE, NOT_HAS_FEATURE)
        self.assertEqual(cluster1.applier_form, af1)
        cluster2 = SuprasegmentalCluster(self.bfm, suprasegmental_characters=
                                         [self.a, self.b])
        af2 = '{0}{1}{2}{3}{3}'.format(AFM, SNFM, HAS_FEATURE, NOT_HAS_FEATURE)
        self.assertEqual(cluster2.applier_form, af2)
    
    def test_normalised_form (self):
        cluster1 = SuprasegmentalCluster(self.bfm, suprasegmental_characters=
                                         [self.a])
        nf1 = NormalisedForm('{0}{1}{2}{3}'.format(
                SNFM, HAS_FEATURE, INAPPLICABLE_FEATURE, NOT_HAS_FEATURE))
        self.assertEqual(cluster1.normalised_form, nf1)
        cluster2 = SuprasegmentalCluster(self.bfm, suprasegmental_characters=
                                         [self.a, self.b])
        nf2 = NormalisedForm('{0}{1}{2}{2}'.format(
                SNFM, HAS_FEATURE, NOT_HAS_FEATURE))
        self.assertEqual(cluster2.normalised_form, nf2)
        cluster3 = Cluster(self.bfm, normalised_form=nf2)
        self.assertEqual(cluster3.normalised_form, nf2)

    def test_string_form (self):
        cluster1 = SuprasegmentalCluster(self.bfm, suprasegmental_characters=
                                         [self.a])
        self.assertEqual(str(cluster1), 'a')
        cluster2 = SuprasegmentalCluster(self.bfm, suprasegmental_characters=
                                         [self.a, self.b])
        self.assertEqual(str(cluster2), 'ab')
        cluster3 = SuprasegmentalCluster(self.bfm, suprasegmental_characters=
                                         [self.b, self.a])
        self.assertEqual(str(cluster3), 'ba')
        
    def test_suprasegmental_cluster_creation_illegal (self):
        bfm1 = BinaryFeaturesModel()
        bfm2 = BinaryFeaturesModel()
        character1 = BaseCharacter(bfm1, 'a')
        character3 = SuprasegmentalCharacter(bfm1, 'b')
        character4 = SuprasegmentalCharacter(bfm2, 'c')
        nf1 = NormalisedForm('{}{}'.format(SNFM, HAS_FEATURE))
        # A SuprasegmentalCluster must be initialised with at least
        # one suprasegmental character or a normalised form.
        self.assertRaises(IllegalArgumentError, SuprasegmentalCluster, bfm1)
        # A SuprasegmentalCluster must not be initialised with both
        # suprasegmental characters and a normalised form.
        self.assertRaises(IllegalArgumentError, SuprasegmentalCluster, bfm1,
                          suprasegmental_characters=[character3],
                          normalised_form=nf1)
        # All of the characters in a cluster must be associated with
        # the same binary features model.
        self.assertRaises(MismatchedModelsError, SuprasegmentalCluster, bfm1,
                          suprasegmental_characters=[character4])
        # All of the characters in a cluster must be suprasegmental.
        self.assertRaises(MismatchedTypesError, SuprasegmentalCluster, bfm1,
                          suprasegmental_characters=[character1, character3])