Upgrade fonttools to 3.43.2

Test: None
Change-Id: Ib4697405ace10cfea684f2c25469558c67319c19
diff --git a/Lib/fontTools/__init__.py b/Lib/fontTools/__init__.py
index d6919b2..1a49c10 100644
--- a/Lib/fontTools/__init__.py
+++ b/Lib/fontTools/__init__.py
@@ -5,6 +5,6 @@
 
 log = logging.getLogger(__name__)
 
-version = __version__ = "3.43.1"
+version = __version__ = "3.43.2"
 
 __all__ = ["version", "log", "configLogger"]
diff --git a/Lib/fontTools/varLib/__init__.py b/Lib/fontTools/varLib/__init__.py
index 891e92c..b428aeb 100644
--- a/Lib/fontTools/varLib/__init__.py
+++ b/Lib/fontTools/varLib/__init__.py
@@ -23,8 +23,7 @@
 from fontTools.misc.py23 import *
 from fontTools.misc.fixedTools import otRound
 from fontTools.misc.arrayTools import Vector
-from fontTools.ttLib import TTFont, newTable, TTLibError
-from fontTools.ttLib.tables._n_a_m_e import NameRecord
+from fontTools.ttLib import TTFont, newTable
 from fontTools.ttLib.tables._f_v_a_r import Axis, NamedInstance
 from fontTools.ttLib.tables._g_l_y_f import GlyphCoordinates
 from fontTools.ttLib.tables.ttProgram import Program
@@ -36,7 +35,7 @@
 from fontTools.varLib.mvar import MVAR_ENTRIES
 from fontTools.varLib.iup import iup_delta_optimize
 from fontTools.varLib.featureVars import addFeatureVariations
-from fontTools.designspaceLib import DesignSpaceDocument, AxisDescriptor
+from fontTools.designspaceLib import DesignSpaceDocument
 from collections import OrderedDict, namedtuple
 import os.path
 import logging
@@ -857,6 +856,45 @@
 	)
 
 
+# https://docs.microsoft.com/en-us/typography/opentype/spec/os2#uswidthclass
+WDTH_VALUE_TO_OS2_WIDTH_CLASS = {
+	50: 1,
+	62.5: 2,
+	75: 3,
+	87.5: 4,
+	100: 5,
+	112.5: 6,
+	125: 7,
+	150: 8,
+	200: 9,
+}
+
+
+def set_default_weight_width_slant(font, location):
+	if "OS/2" in font:
+		if "wght" in location:
+			weight_class = otRound(max(1, min(location["wght"], 1000)))
+			if font["OS/2"].usWeightClass != weight_class:
+				log.info("Setting OS/2.usWidthClass = %s", weight_class)
+				font["OS/2"].usWeightClass = weight_class
+
+		if "wdth" in location:
+			# map 'wdth' axis (50..200) to OS/2.usWidthClass (1..9), rounding to closest
+			widthValue = min(max(location["wdth"], 50), 200)
+			widthClass = otRound(
+				models.piecewiseLinearMap(widthValue, WDTH_VALUE_TO_OS2_WIDTH_CLASS)
+			)
+			if font["OS/2"].usWidthClass != widthClass:
+				log.info("Setting OS/2.usWidthClass = %s", widthClass)
+				font["OS/2"].usWidthClass = widthClass
+
+	if "slnt" in location and "post" in font:
+		italicAngle = max(-90, min(location["slnt"], 90))
+		if font["post"].italicAngle != italicAngle:
+			log.info("Setting post.italicAngle = %s", italicAngle)
+			font["post"].italicAngle = italicAngle
+
+
 def build(designspace, master_finder=lambda s:s, exclude=[], optimize=True):
 	"""
 	Build variation font from a designspace file.
@@ -930,6 +968,10 @@
 				post.extraNames = []
 				post.mapping = {}
 
+	set_default_weight_width_slant(
+		vf, location={axis.axisTag: axis.defaultValue for axis in vf["fvar"].axes}
+	)
+
 	for tag in exclude:
 		if tag in vf:
 			del vf[tag]
@@ -1064,9 +1106,6 @@
 
 	designspace_filename = options.designspace
 	finder = MasterFinder(options.master_finder)
-	outfile = options.outfile
-	if outfile is None:
-		outfile = os.path.splitext(designspace_filename)[0] + '-VF.ttf'
 
 	vf, _, _ = build(
 		designspace_filename,
@@ -1075,6 +1114,11 @@
 		optimize=options.optimize
 	)
 
+	outfile = options.outfile
+	if outfile is None:
+		ext = "otf" if vf.sfntVersion == "OTTO" else "ttf"
+		outfile = os.path.splitext(designspace_filename)[0] + '-VF.' + ext
+
 	log.info("Saving variation font %s", outfile)
 	vf.save(outfile)
 
diff --git a/Lib/fontTools/varLib/cff.py b/Lib/fontTools/varLib/cff.py
old mode 100755
new mode 100644
index bcafdee..aaabf85
--- a/Lib/fontTools/varLib/cff.py
+++ b/Lib/fontTools/varLib/cff.py
@@ -131,7 +131,7 @@
 
 
 def conv_to_int(num):
-	if num % 1 == 0:
+	if isinstance(num, float) and num.is_integer():
 		return int(num)
 	return num
 
@@ -198,17 +198,17 @@
 			pds.append(pd)
 		num_masters = len(pds)
 		for key, value in private_dict.rawDict.items():
+			dataList = []
 			if key not in pd_blend_fields:
 				continue
 			if isinstance(value, list):
 				try:
 					values = [pd.rawDict[key] for pd in pds]
 				except KeyError:
-					del private_dict.rawDict[key]
 					print(
-						b"Warning: {key} in default font Private dict is "
-						b"missing from another font, and was "
-						b"discarded.".format(key=key))
+						"Warning: {key} in default font Private dict is "
+						"missing from another font, and was "
+						"discarded.".format(key=key))
 					continue
 				try:
 					values = zip(*values)
@@ -227,7 +227,6 @@
 				and is converted finally to:
 				OtherBlues = [[-217, 17.0, 46.0], [-205, 0.0, 0.0]]
 				"""
-				dataList = []
 				prev_val_list = [0] * num_masters
 				any_points_differ = False
 				for val_list in values:
@@ -237,8 +236,6 @@
 						any_points_differ = True
 					prev_val_list = val_list
 					deltas = sub_model.getDeltas(rel_list)
-					# Convert numbers with no decimal part to an int.
-					deltas = [conv_to_int(delta) for delta in deltas]
 					# For PrivateDict BlueValues, the default font
 					# values are absolute, not relative to the prior value.
 					deltas[0] = val_list[0]
@@ -253,6 +250,18 @@
 					dataList = sub_model.getDeltas(values)
 				else:
 					dataList = values[0]
+
+			# Convert numbers with no decimal part to an int
+			if isinstance(dataList, list):
+				for i, item in enumerate(dataList):
+					if isinstance(item, list):
+						for j, jtem in enumerate(item):
+							dataList[i][j] = conv_to_int(jtem)
+					else:
+						dataList[i] = conv_to_int(item)
+			else:
+				dataList = conv_to_int(dataList)
+
 			private_dict.rawDict[key] = dataList
 
 
@@ -270,7 +279,7 @@
 	num_regions = len(region_fonts)
 	topDict = default_font['CFF '].cff.topDictIndex[0]
 	if not hasattr(topDict, 'FDSelect'):
-		# All glyphs reference only one FontDict. 
+		# All glyphs reference only one FontDict.
 		# Map the FD index for regions to index 0.
 		fd_map[0] = {ri:0 for ri in range(num_regions)}
 		return fd_map
@@ -390,9 +399,9 @@
 		# as we know it doesn't exist yet.
 		if vsindex != 0:
 			new_cs.program[:0] = [vsindex, 'vsindex']
-			
+
 	# If there is no variation in any of the charstrings, then vsindex_dict
-	# never gets built. This could still be needed if there is variation 
+	# never gets built. This could still be needed if there is variation
 	# in the PrivatDict, so we will build the default data for vsindex = 0.
 	if not vsindex_dict:
 		key = (True,) * num_masters
diff --git a/Lib/fontTools/varLib/featureVars.py b/Lib/fontTools/varLib/featureVars.py
index 4caf30a..e3aa6b6 100644
--- a/Lib/fontTools/varLib/featureVars.py
+++ b/Lib/fontTools/varLib/featureVars.py
@@ -71,7 +71,7 @@
     and rules with the same Box merged.  The more specific rules appear earlier
     in the resulting list.  Moreover, instead of just a dictionary of substitutions,
     a list of dictionaries is returned for substitutions corresponding to each
-    uniq space, with each dictionary being identical to one of the input
+    unique space, with each dictionary being identical to one of the input
     substitution dictionaries.  These dictionaries are not merged to allow data
     sharing when they are converted into font tables.
 
@@ -79,6 +79,7 @@
     >>> condSubst = [
     ...     # A list of (Region, Substitution) tuples.
     ...     ([{"wght": (0.5, 1.0)}], {"dollar": "dollar.rvrn"}),
+    ...     ([{"wght": (0.5, 1.0)}], {"dollar": "dollar.rvrn"}),
     ...     ([{"wdth": (0.5, 1.0)}], {"cent": "cent.rvrn"}),
     ... ]
     >>> from pprint import pprint
@@ -107,7 +108,8 @@
     # rules for the same region.
     merged = OrderedDict()
     for key,value in reversed(conditionalSubstitutions):
-        key = tuple(sorted(hashdict(cleanupBox(k)) for k in key))
+        key = tuple(sorted((hashdict(cleanupBox(k)) for k in key),
+                           key=lambda d: tuple(sorted(d.items()))))
         if key in merged:
             merged[key].update(value)
         else:
diff --git a/Lib/fonttools.egg-info/PKG-INFO b/Lib/fonttools.egg-info/PKG-INFO
index 74bb40d..2dc1e57 100644
--- a/Lib/fonttools.egg-info/PKG-INFO
+++ b/Lib/fonttools.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: fonttools
-Version: 3.43.1
+Version: 3.43.2
 Summary: Tools to manipulate font files
 Home-page: http://github.com/fonttools/fonttools
 Author: Just van Rossum
@@ -415,6 +415,12 @@
         Changelog
         ~~~~~~~~~
         
+        3.43.2 (released 2019-07-10)
+        ----------------------------
+        
+        - [featureVars] Fixed region-merging code on python3 (#1659).
+        - [varLib.cff] Fixed merging of sparse PrivateDict items (#1653).
+        
         3.43.1 (released 2019-06-19)
         ----------------------------
         
@@ -1787,13 +1793,13 @@
 Classifier: Topic :: Text Processing :: Fonts
 Classifier: Topic :: Multimedia :: Graphics
 Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
+Provides-Extra: plot
+Provides-Extra: unicode
+Provides-Extra: all
 Provides-Extra: lxml
 Provides-Extra: interpolatable
-Provides-Extra: unicode
+Provides-Extra: woff
+Provides-Extra: symfont
 Provides-Extra: type1
-Provides-Extra: all
 Provides-Extra: ufo
 Provides-Extra: graphite
-Provides-Extra: woff
-Provides-Extra: plot
-Provides-Extra: symfont
diff --git a/METADATA b/METADATA
index ef73891..61c9a71 100644
--- a/METADATA
+++ b/METADATA
@@ -7,12 +7,12 @@
   }
   url {
     type: ARCHIVE
-    value: "https://github.com/fonttools/fonttools/releases/download/3.43.1/fonttools-3.43.1.zip"
+    value: "https://github.com/fonttools/fonttools/releases/download/3.43.2/fonttools-3.43.2.zip"
   }
-  version: "3.43.1"
+  version: "3.43.2"
   last_upgrade_date {
     year: 2019
-    month: 6
-    day: 19
+    month: 7
+    day: 10
   }
 }
diff --git a/NEWS.rst b/NEWS.rst
index b7b1b50..0105e42 100644
--- a/NEWS.rst
+++ b/NEWS.rst
@@ -1,3 +1,9 @@
+3.43.2 (released 2019-07-10)
+----------------------------
+
+- [featureVars] Fixed region-merging code on python3 (#1659).
+- [varLib.cff] Fixed merging of sparse PrivateDict items (#1653).
+
 3.43.1 (released 2019-06-19)
 ----------------------------
 
diff --git a/PKG-INFO b/PKG-INFO
index 74bb40d..2dc1e57 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: fonttools
-Version: 3.43.1
+Version: 3.43.2
 Summary: Tools to manipulate font files
 Home-page: http://github.com/fonttools/fonttools
 Author: Just van Rossum
@@ -415,6 +415,12 @@
         Changelog
         ~~~~~~~~~
         
+        3.43.2 (released 2019-07-10)
+        ----------------------------
+        
+        - [featureVars] Fixed region-merging code on python3 (#1659).
+        - [varLib.cff] Fixed merging of sparse PrivateDict items (#1653).
+        
         3.43.1 (released 2019-06-19)
         ----------------------------
         
@@ -1787,13 +1793,13 @@
 Classifier: Topic :: Text Processing :: Fonts
 Classifier: Topic :: Multimedia :: Graphics
 Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
+Provides-Extra: plot
+Provides-Extra: unicode
+Provides-Extra: all
 Provides-Extra: lxml
 Provides-Extra: interpolatable
-Provides-Extra: unicode
+Provides-Extra: woff
+Provides-Extra: symfont
 Provides-Extra: type1
-Provides-Extra: all
 Provides-Extra: ufo
 Provides-Extra: graphite
-Provides-Extra: woff
-Provides-Extra: plot
-Provides-Extra: symfont
diff --git a/Tests/otlLib/builder_test.py b/Tests/otlLib/builder_test.py
index 0829176..83f7c82 100644
--- a/Tests/otlLib/builder_test.py
+++ b/Tests/otlLib/builder_test.py
@@ -3,1011 +3,1071 @@
 from fontTools.misc.testTools import getXML
 from fontTools.otlLib import builder
 from fontTools.ttLib.tables import otTables
-from itertools import chain
-import unittest
+import pytest
 
 
-class BuilderTest(unittest.TestCase):
-    GLYPHS = (".notdef space zero one two three four five six "
-              "A B C a b c grave acute cedilla f_f_i f_i c_t").split()
+class BuilderTest(object):
+    GLYPHS = (
+        ".notdef space zero one two three four five six "
+        "A B C a b c grave acute cedilla f_f_i f_i c_t"
+    ).split()
     GLYPHMAP = {name: num for num, name in enumerate(GLYPHS)}
 
     ANCHOR1 = builder.buildAnchor(11, -11)
     ANCHOR2 = builder.buildAnchor(22, -22)
     ANCHOR3 = builder.buildAnchor(33, -33)
 
-    def __init__(self, methodName):
-        unittest.TestCase.__init__(self, methodName)
-        # Python 3 renamed assertRaisesRegexp to assertRaisesRegex,
-        # and fires deprecation warnings if a program uses the old name.
-        if not hasattr(self, "assertRaisesRegex"):
-            self.assertRaisesRegex = self.assertRaisesRegexp
-
-    @classmethod
-    def setUpClass(cls):
-        cls.maxDiff = None
-
     def test_buildAnchor_format1(self):
         anchor = builder.buildAnchor(23, 42)
-        self.assertEqual(getXML(anchor.toXML),
-                         ['<Anchor Format="1">',
-                          '  <XCoordinate value="23"/>',
-                          '  <YCoordinate value="42"/>',
-                          '</Anchor>'])
+        assert getXML(anchor.toXML) == [
+            '<Anchor Format="1">',
+            '  <XCoordinate value="23"/>',
+            '  <YCoordinate value="42"/>',
+            "</Anchor>",
+        ]
 
     def test_buildAnchor_format2(self):
         anchor = builder.buildAnchor(23, 42, point=17)
-        self.assertEqual(getXML(anchor.toXML),
-                         ['<Anchor Format="2">',
-                          '  <XCoordinate value="23"/>',
-                          '  <YCoordinate value="42"/>',
-                          '  <AnchorPoint value="17"/>',
-                          '</Anchor>'])
+        assert getXML(anchor.toXML) == [
+            '<Anchor Format="2">',
+            '  <XCoordinate value="23"/>',
+            '  <YCoordinate value="42"/>',
+            '  <AnchorPoint value="17"/>',
+            "</Anchor>",
+        ]
 
     def test_buildAnchor_format3(self):
         anchor = builder.buildAnchor(
-            23, 42,
+            23,
+            42,
             deviceX=builder.buildDevice({1: 1, 0: 0}),
-            deviceY=builder.buildDevice({7: 7}))
-        self.assertEqual(getXML(anchor.toXML),
-                         ['<Anchor Format="3">',
-                          '  <XCoordinate value="23"/>',
-                          '  <YCoordinate value="42"/>',
-                          '  <XDeviceTable>',
-                          '    <StartSize value="0"/>',
-                          '    <EndSize value="1"/>',
-                          '    <DeltaFormat value="1"/>',
-                          '    <DeltaValue value="[0, 1]"/>',
-                          '  </XDeviceTable>',
-                          '  <YDeviceTable>',
-                          '    <StartSize value="7"/>',
-                          '    <EndSize value="7"/>',
-                          '    <DeltaFormat value="2"/>',
-                          '    <DeltaValue value="[7]"/>',
-                          '  </YDeviceTable>',
-                          '</Anchor>'])
+            deviceY=builder.buildDevice({7: 7}),
+        )
+        assert getXML(anchor.toXML) == [
+            '<Anchor Format="3">',
+            '  <XCoordinate value="23"/>',
+            '  <YCoordinate value="42"/>',
+            "  <XDeviceTable>",
+            '    <StartSize value="0"/>',
+            '    <EndSize value="1"/>',
+            '    <DeltaFormat value="1"/>',
+            '    <DeltaValue value="[0, 1]"/>',
+            "  </XDeviceTable>",
+            "  <YDeviceTable>",
+            '    <StartSize value="7"/>',
+            '    <EndSize value="7"/>',
+            '    <DeltaFormat value="2"/>',
+            '    <DeltaValue value="[7]"/>',
+            "  </YDeviceTable>",
+            "</Anchor>",
+        ]
 
     def test_buildAttachList(self):
-        attachList = builder.buildAttachList({
-            "zero": [23, 7], "one": [1],
-        }, self.GLYPHMAP)
-        self.assertEqual(getXML(attachList.toXML),
-                         ['<AttachList>',
-                          '  <Coverage>',
-                          '    <Glyph value="zero"/>',
-                          '    <Glyph value="one"/>',
-                          '  </Coverage>',
-                          '  <!-- GlyphCount=2 -->',
-                          '  <AttachPoint index="0">',
-                          '    <!-- PointCount=2 -->',
-                          '    <PointIndex index="0" value="7"/>',
-                          '    <PointIndex index="1" value="23"/>',
-                          '  </AttachPoint>',
-                          '  <AttachPoint index="1">',
-                          '    <!-- PointCount=1 -->',
-                          '    <PointIndex index="0" value="1"/>',
-                          '  </AttachPoint>',
-                          '</AttachList>'])
+        attachList = builder.buildAttachList(
+            {"zero": [23, 7], "one": [1]}, self.GLYPHMAP
+        )
+        assert getXML(attachList.toXML) == [
+            "<AttachList>",
+            "  <Coverage>",
+            '    <Glyph value="zero"/>',
+            '    <Glyph value="one"/>',
+            "  </Coverage>",
+            "  <!-- GlyphCount=2 -->",
+            '  <AttachPoint index="0">',
+            "    <!-- PointCount=2 -->",
+            '    <PointIndex index="0" value="7"/>',
+            '    <PointIndex index="1" value="23"/>',
+            "  </AttachPoint>",
+            '  <AttachPoint index="1">',
+            "    <!-- PointCount=1 -->",
+            '    <PointIndex index="0" value="1"/>',
+            "  </AttachPoint>",
+            "</AttachList>",
+        ]
 
     def test_buildAttachList_empty(self):
-        self.assertIsNone(builder.buildAttachList({}, self.GLYPHMAP))
+        assert builder.buildAttachList({}, self.GLYPHMAP) is None
 
     def test_buildAttachPoint(self):
         attachPoint = builder.buildAttachPoint([7, 3])
-        self.assertEqual(getXML(attachPoint.toXML),
-                         ['<AttachPoint>',
-                          '  <!-- PointCount=2 -->',
-                          '  <PointIndex index="0" value="3"/>',
-                          '  <PointIndex index="1" value="7"/>',
-                          '</AttachPoint>'])
+        assert getXML(attachPoint.toXML) == [
+            "<AttachPoint>",
+            "  <!-- PointCount=2 -->",
+            '  <PointIndex index="0" value="3"/>',
+            '  <PointIndex index="1" value="7"/>',
+            "</AttachPoint>",
+        ]
 
     def test_buildAttachPoint_empty(self):
-        self.assertIsNone(builder.buildAttachPoint([]))
+        assert builder.buildAttachPoint([]) is None
 
     def test_buildAttachPoint_duplicate(self):
         attachPoint = builder.buildAttachPoint([7, 3, 7])
-        self.assertEqual(getXML(attachPoint.toXML),
-                         ['<AttachPoint>',
-                          '  <!-- PointCount=2 -->',
-                          '  <PointIndex index="0" value="3"/>',
-                          '  <PointIndex index="1" value="7"/>',
-                          '</AttachPoint>'])
-
+        assert getXML(attachPoint.toXML) == [
+            "<AttachPoint>",
+            "  <!-- PointCount=2 -->",
+            '  <PointIndex index="0" value="3"/>',
+            '  <PointIndex index="1" value="7"/>',
+            "</AttachPoint>",
+        ]
 
     def test_buildBaseArray(self):
         anchor = builder.buildAnchor
-        baseArray = builder.buildBaseArray({
-            "a": {2: anchor(300, 80)},
-            "c": {1: anchor(300, 80), 2: anchor(300, -20)}
-        }, numMarkClasses=4, glyphMap=self.GLYPHMAP)
-        self.assertEqual(getXML(baseArray.toXML),
-                         ['<BaseArray>',
-                          '  <!-- BaseCount=2 -->',
-                          '  <BaseRecord index="0">',
-                          '    <BaseAnchor index="0" empty="1"/>',
-                          '    <BaseAnchor index="1" empty="1"/>',
-                          '    <BaseAnchor index="2" Format="1">',
-                          '      <XCoordinate value="300"/>',
-                          '      <YCoordinate value="80"/>',
-                          '    </BaseAnchor>',
-                          '    <BaseAnchor index="3" empty="1"/>',
-                          '  </BaseRecord>',
-                          '  <BaseRecord index="1">',
-                          '    <BaseAnchor index="0" empty="1"/>',
-                          '    <BaseAnchor index="1" Format="1">',
-                          '      <XCoordinate value="300"/>',
-                          '      <YCoordinate value="80"/>',
-                          '    </BaseAnchor>',
-                          '    <BaseAnchor index="2" Format="1">',
-                          '      <XCoordinate value="300"/>',
-                          '      <YCoordinate value="-20"/>',
-                          '    </BaseAnchor>',
-                          '    <BaseAnchor index="3" empty="1"/>',
-                          '  </BaseRecord>',
-                          '</BaseArray>'])
+        baseArray = builder.buildBaseArray(
+            {"a": {2: anchor(300, 80)}, "c": {1: anchor(300, 80), 2: anchor(300, -20)}},
+            numMarkClasses=4,
+            glyphMap=self.GLYPHMAP,
+        )
+        assert getXML(baseArray.toXML) == [
+            "<BaseArray>",
+            "  <!-- BaseCount=2 -->",
+            '  <BaseRecord index="0">',
+            '    <BaseAnchor index="0" empty="1"/>',
+            '    <BaseAnchor index="1" empty="1"/>',
+            '    <BaseAnchor index="2" Format="1">',
+            '      <XCoordinate value="300"/>',
+            '      <YCoordinate value="80"/>',
+            "    </BaseAnchor>",
+            '    <BaseAnchor index="3" empty="1"/>',
+            "  </BaseRecord>",
+            '  <BaseRecord index="1">',
+            '    <BaseAnchor index="0" empty="1"/>',
+            '    <BaseAnchor index="1" Format="1">',
+            '      <XCoordinate value="300"/>',
+            '      <YCoordinate value="80"/>',
+            "    </BaseAnchor>",
+            '    <BaseAnchor index="2" Format="1">',
+            '      <XCoordinate value="300"/>',
+            '      <YCoordinate value="-20"/>',
+            "    </BaseAnchor>",
+            '    <BaseAnchor index="3" empty="1"/>',
+            "  </BaseRecord>",
+            "</BaseArray>",
+        ]
 
     def test_buildBaseRecord(self):
         a = builder.buildAnchor
         rec = builder.buildBaseRecord([a(500, -20), None, a(300, -15)])
-        self.assertEqual(getXML(rec.toXML),
-                         ['<BaseRecord>',
-                          '  <BaseAnchor index="0" Format="1">',
-                          '    <XCoordinate value="500"/>',
-                          '    <YCoordinate value="-20"/>',
-                          '  </BaseAnchor>',
-                          '  <BaseAnchor index="1" empty="1"/>',
-                          '  <BaseAnchor index="2" Format="1">',
-                          '    <XCoordinate value="300"/>',
-                          '    <YCoordinate value="-15"/>',
-                          '  </BaseAnchor>',
-                          '</BaseRecord>'])
+        assert getXML(rec.toXML) == [
+            "<BaseRecord>",
+            '  <BaseAnchor index="0" Format="1">',
+            '    <XCoordinate value="500"/>',
+            '    <YCoordinate value="-20"/>',
+            "  </BaseAnchor>",
+            '  <BaseAnchor index="1" empty="1"/>',
+            '  <BaseAnchor index="2" Format="1">',
+            '    <XCoordinate value="300"/>',
+            '    <YCoordinate value="-15"/>',
+            "  </BaseAnchor>",
+            "</BaseRecord>",
+        ]
 
     def test_buildCaretValueForCoord(self):
         caret = builder.buildCaretValueForCoord(500)
-        self.assertEqual(getXML(caret.toXML),
-                         ['<CaretValue Format="1">',
-                          '  <Coordinate value="500"/>',
-                          '</CaretValue>'])
+        assert getXML(caret.toXML) == [
+            '<CaretValue Format="1">',
+            '  <Coordinate value="500"/>',
+            "</CaretValue>",
+        ]
 
     def test_buildCaretValueForPoint(self):
         caret = builder.buildCaretValueForPoint(23)
-        self.assertEqual(getXML(caret.toXML),
-                         ['<CaretValue Format="2">',
-                          '  <CaretValuePoint value="23"/>',
-                          '</CaretValue>'])
+        assert getXML(caret.toXML) == [
+            '<CaretValue Format="2">',
+            '  <CaretValuePoint value="23"/>',
+            "</CaretValue>",
+        ]
 
     def test_buildComponentRecord(self):
         a = builder.buildAnchor
         rec = builder.buildComponentRecord([a(500, -20), None, a(300, -15)])
-        self.assertEqual(getXML(rec.toXML),
-                         ['<ComponentRecord>',
-                          '  <LigatureAnchor index="0" Format="1">',
-                          '    <XCoordinate value="500"/>',
-                          '    <YCoordinate value="-20"/>',
-                          '  </LigatureAnchor>',
-                          '  <LigatureAnchor index="1" empty="1"/>',
-                          '  <LigatureAnchor index="2" Format="1">',
-                          '    <XCoordinate value="300"/>',
-                          '    <YCoordinate value="-15"/>',
-                          '  </LigatureAnchor>',
-                          '</ComponentRecord>'])
+        assert getXML(rec.toXML) == [
+            "<ComponentRecord>",
+            '  <LigatureAnchor index="0" Format="1">',
+            '    <XCoordinate value="500"/>',
+            '    <YCoordinate value="-20"/>',
+            "  </LigatureAnchor>",
+            '  <LigatureAnchor index="1" empty="1"/>',
+            '  <LigatureAnchor index="2" Format="1">',
+            '    <XCoordinate value="300"/>',
+            '    <YCoordinate value="-15"/>',
+            "  </LigatureAnchor>",
+            "</ComponentRecord>",
+        ]
 
     def test_buildComponentRecord_empty(self):
-        self.assertIsNone(builder.buildComponentRecord([]))
+        assert builder.buildComponentRecord([]) is None
 
     def test_buildComponentRecord_None(self):
-        self.assertIsNone(builder.buildComponentRecord(None))
+        assert builder.buildComponentRecord(None) is None
 
     def test_buildCoverage(self):
         cov = builder.buildCoverage({"two", "four"}, {"two": 2, "four": 4})
-        self.assertEqual(getXML(cov.toXML),
-                         ['<Coverage>',
-                          '  <Glyph value="two"/>',
-                          '  <Glyph value="four"/>',
-                          '</Coverage>'])
+        assert getXML(cov.toXML) == [
+            "<Coverage>",
+            '  <Glyph value="two"/>',
+            '  <Glyph value="four"/>',
+            "</Coverage>",
+        ]
 
     def test_buildCursivePos(self):
-        pos = builder.buildCursivePosSubtable({
-            "two": (self.ANCHOR1, self.ANCHOR2),
-            "four": (self.ANCHOR3, self.ANCHOR1)
-        }, self.GLYPHMAP)
-        self.assertEqual(getXML(pos.toXML),
-                         ['<CursivePos Format="1">',
-                          '  <Coverage>',
-                          '    <Glyph value="two"/>',
-                          '    <Glyph value="four"/>',
-                          '  </Coverage>',
-                          '  <!-- EntryExitCount=2 -->',
-                          '  <EntryExitRecord index="0">',
-                          '    <EntryAnchor Format="1">',
-                          '      <XCoordinate value="11"/>',
-                          '      <YCoordinate value="-11"/>',
-                          '    </EntryAnchor>',
-                          '    <ExitAnchor Format="1">',
-                          '      <XCoordinate value="22"/>',
-                          '      <YCoordinate value="-22"/>',
-                          '    </ExitAnchor>',
-                          '  </EntryExitRecord>',
-                          '  <EntryExitRecord index="1">',
-                          '    <EntryAnchor Format="1">',
-                          '      <XCoordinate value="33"/>',
-                          '      <YCoordinate value="-33"/>',
-                          '    </EntryAnchor>',
-                          '    <ExitAnchor Format="1">',
-                          '      <XCoordinate value="11"/>',
-                          '      <YCoordinate value="-11"/>',
-                          '    </ExitAnchor>',
-                          '  </EntryExitRecord>',
-                          '</CursivePos>'])
+        pos = builder.buildCursivePosSubtable(
+            {"two": (self.ANCHOR1, self.ANCHOR2), "four": (self.ANCHOR3, self.ANCHOR1)},
+            self.GLYPHMAP,
+        )
+        assert getXML(pos.toXML) == [
+            '<CursivePos Format="1">',
+            "  <Coverage>",
+            '    <Glyph value="two"/>',
+            '    <Glyph value="four"/>',
+            "  </Coverage>",
+            "  <!-- EntryExitCount=2 -->",
+            '  <EntryExitRecord index="0">',
+            '    <EntryAnchor Format="1">',
+            '      <XCoordinate value="11"/>',
+            '      <YCoordinate value="-11"/>',
+            "    </EntryAnchor>",
+            '    <ExitAnchor Format="1">',
+            '      <XCoordinate value="22"/>',
+            '      <YCoordinate value="-22"/>',
+            "    </ExitAnchor>",
+            "  </EntryExitRecord>",
+            '  <EntryExitRecord index="1">',
+            '    <EntryAnchor Format="1">',
+            '      <XCoordinate value="33"/>',
+            '      <YCoordinate value="-33"/>',
+            "    </EntryAnchor>",
+            '    <ExitAnchor Format="1">',
+            '      <XCoordinate value="11"/>',
+            '      <YCoordinate value="-11"/>',
+            "    </ExitAnchor>",
+            "  </EntryExitRecord>",
+            "</CursivePos>",
+        ]
 
     def test_buildDevice_format1(self):
-        device = builder.buildDevice({1:1, 0:0})
-        self.assertEqual(getXML(device.toXML),
-                         ['<Device>',
-                          '  <StartSize value="0"/>',
-                          '  <EndSize value="1"/>',
-                          '  <DeltaFormat value="1"/>',
-                          '  <DeltaValue value="[0, 1]"/>',
-                          '</Device>'])
+        device = builder.buildDevice({1: 1, 0: 0})
+        assert getXML(device.toXML) == [
+            "<Device>",
+            '  <StartSize value="0"/>',
+            '  <EndSize value="1"/>',
+            '  <DeltaFormat value="1"/>',
+            '  <DeltaValue value="[0, 1]"/>',
+            "</Device>",
+        ]
 
     def test_buildDevice_format2(self):
-        device = builder.buildDevice({2:2, 0:1, 1:0})
-        self.assertEqual(getXML(device.toXML),
-                         ['<Device>',
-                          '  <StartSize value="0"/>',
-                          '  <EndSize value="2"/>',
-                          '  <DeltaFormat value="2"/>',
-                          '  <DeltaValue value="[1, 0, 2]"/>',
-                          '</Device>'])
+        device = builder.buildDevice({2: 2, 0: 1, 1: 0})
+        assert getXML(device.toXML) == [
+            "<Device>",
+            '  <StartSize value="0"/>',
+            '  <EndSize value="2"/>',
+            '  <DeltaFormat value="2"/>',
+            '  <DeltaValue value="[1, 0, 2]"/>',
+            "</Device>",
+        ]
 
     def test_buildDevice_format3(self):
-        device = builder.buildDevice({5:3, 1:77})
-        self.assertEqual(getXML(device.toXML),
-                         ['<Device>',
-                          '  <StartSize value="1"/>',
-                          '  <EndSize value="5"/>',
-                          '  <DeltaFormat value="3"/>',
-                          '  <DeltaValue value="[77, 0, 0, 0, 3]"/>',
-                          '</Device>'])
+        device = builder.buildDevice({5: 3, 1: 77})
+        assert getXML(device.toXML) == [
+            "<Device>",
+            '  <StartSize value="1"/>',
+            '  <EndSize value="5"/>',
+            '  <DeltaFormat value="3"/>',
+            '  <DeltaValue value="[77, 0, 0, 0, 3]"/>',
+            "</Device>",
+        ]
 
     def test_buildLigatureArray(self):
         anchor = builder.buildAnchor
-        ligatureArray = builder.buildLigatureArray({
-            "f_i": [{2: anchor(300, -20)}, {}],
-            "c_t": [{}, {1: anchor(500, 350), 2: anchor(1300, -20)}]
-        }, numMarkClasses=4, glyphMap=self.GLYPHMAP)
-        self.assertEqual(getXML(ligatureArray.toXML),
-                         ['<LigatureArray>',
-                          '  <!-- LigatureCount=2 -->',
-                          '  <LigatureAttach index="0">',  # f_i
-                          '    <!-- ComponentCount=2 -->',
-                          '    <ComponentRecord index="0">',
-                          '      <LigatureAnchor index="0" empty="1"/>',
-                          '      <LigatureAnchor index="1" empty="1"/>',
-                          '      <LigatureAnchor index="2" Format="1">',
-                          '        <XCoordinate value="300"/>',
-                          '        <YCoordinate value="-20"/>',
-                          '      </LigatureAnchor>',
-                          '      <LigatureAnchor index="3" empty="1"/>',
-                          '    </ComponentRecord>',
-                          '    <ComponentRecord index="1">',
-                          '      <LigatureAnchor index="0" empty="1"/>',
-                          '      <LigatureAnchor index="1" empty="1"/>',
-                          '      <LigatureAnchor index="2" empty="1"/>',
-                          '      <LigatureAnchor index="3" empty="1"/>',
-                          '    </ComponentRecord>',
-                          '  </LigatureAttach>',
-                          '  <LigatureAttach index="1">',
-                          '    <!-- ComponentCount=2 -->',
-                          '    <ComponentRecord index="0">',
-                          '      <LigatureAnchor index="0" empty="1"/>',
-                          '      <LigatureAnchor index="1" empty="1"/>',
-                          '      <LigatureAnchor index="2" empty="1"/>',
-                          '      <LigatureAnchor index="3" empty="1"/>',
-                          '    </ComponentRecord>',
-                          '    <ComponentRecord index="1">',
-                          '      <LigatureAnchor index="0" empty="1"/>',
-                          '      <LigatureAnchor index="1" Format="1">',
-                          '        <XCoordinate value="500"/>',
-                          '        <YCoordinate value="350"/>',
-                          '      </LigatureAnchor>',
-                          '      <LigatureAnchor index="2" Format="1">',
-                          '        <XCoordinate value="1300"/>',
-                          '        <YCoordinate value="-20"/>',
-                          '      </LigatureAnchor>',
-                          '      <LigatureAnchor index="3" empty="1"/>',
-                          '    </ComponentRecord>',
-                          '  </LigatureAttach>',
-                          '</LigatureArray>'])
+        ligatureArray = builder.buildLigatureArray(
+            {
+                "f_i": [{2: anchor(300, -20)}, {}],
+                "c_t": [{}, {1: anchor(500, 350), 2: anchor(1300, -20)}],
+            },
+            numMarkClasses=4,
+            glyphMap=self.GLYPHMAP,
+        )
+        assert getXML(ligatureArray.toXML) == [
+            "<LigatureArray>",
+            "  <!-- LigatureCount=2 -->",
+            '  <LigatureAttach index="0">',  # f_i
+            "    <!-- ComponentCount=2 -->",
+            '    <ComponentRecord index="0">',
+            '      <LigatureAnchor index="0" empty="1"/>',
+            '      <LigatureAnchor index="1" empty="1"/>',
+            '      <LigatureAnchor index="2" Format="1">',
+            '        <XCoordinate value="300"/>',
+            '        <YCoordinate value="-20"/>',
+            "      </LigatureAnchor>",
+            '      <LigatureAnchor index="3" empty="1"/>',
+            "    </ComponentRecord>",
+            '    <ComponentRecord index="1">',
+            '      <LigatureAnchor index="0" empty="1"/>',
+            '      <LigatureAnchor index="1" empty="1"/>',
+            '      <LigatureAnchor index="2" empty="1"/>',
+            '      <LigatureAnchor index="3" empty="1"/>',
+            "    </ComponentRecord>",
+            "  </LigatureAttach>",
+            '  <LigatureAttach index="1">',
+            "    <!-- ComponentCount=2 -->",
+            '    <ComponentRecord index="0">',
+            '      <LigatureAnchor index="0" empty="1"/>',
+            '      <LigatureAnchor index="1" empty="1"/>',
+            '      <LigatureAnchor index="2" empty="1"/>',
+            '      <LigatureAnchor index="3" empty="1"/>',
+            "    </ComponentRecord>",
+            '    <ComponentRecord index="1">',
+            '      <LigatureAnchor index="0" empty="1"/>',
+            '      <LigatureAnchor index="1" Format="1">',
+            '        <XCoordinate value="500"/>',
+            '        <YCoordinate value="350"/>',
+            "      </LigatureAnchor>",
+            '      <LigatureAnchor index="2" Format="1">',
+            '        <XCoordinate value="1300"/>',
+            '        <YCoordinate value="-20"/>',
+            "      </LigatureAnchor>",
+            '      <LigatureAnchor index="3" empty="1"/>',
+            "    </ComponentRecord>",
+            "  </LigatureAttach>",
+            "</LigatureArray>",
+        ]
 
     def test_buildLigatureAttach(self):
         anchor = builder.buildAnchor
-        attach = builder.buildLigatureAttach([
-            [anchor(500, -10), None],
-            [None, anchor(300, -20), None]])
-        self.assertEqual(getXML(attach.toXML),
-                         ['<LigatureAttach>',
-                          '  <!-- ComponentCount=2 -->',
-                          '  <ComponentRecord index="0">',
-                          '    <LigatureAnchor index="0" Format="1">',
-                          '      <XCoordinate value="500"/>',
-                          '      <YCoordinate value="-10"/>',
-                          '    </LigatureAnchor>',
-                          '    <LigatureAnchor index="1" empty="1"/>',
-                          '  </ComponentRecord>',
-                          '  <ComponentRecord index="1">',
-                          '    <LigatureAnchor index="0" empty="1"/>',
-                          '    <LigatureAnchor index="1" Format="1">',
-                          '      <XCoordinate value="300"/>',
-                          '      <YCoordinate value="-20"/>',
-                          '    </LigatureAnchor>',
-                          '    <LigatureAnchor index="2" empty="1"/>',
-                          '  </ComponentRecord>',
-                          '</LigatureAttach>'])
+        attach = builder.buildLigatureAttach(
+            [[anchor(500, -10), None], [None, anchor(300, -20), None]]
+        )
+        assert getXML(attach.toXML) == [
+            "<LigatureAttach>",
+            "  <!-- ComponentCount=2 -->",
+            '  <ComponentRecord index="0">',
+            '    <LigatureAnchor index="0" Format="1">',
+            '      <XCoordinate value="500"/>',
+            '      <YCoordinate value="-10"/>',
+            "    </LigatureAnchor>",
+            '    <LigatureAnchor index="1" empty="1"/>',
+            "  </ComponentRecord>",
+            '  <ComponentRecord index="1">',
+            '    <LigatureAnchor index="0" empty="1"/>',
+            '    <LigatureAnchor index="1" Format="1">',
+            '      <XCoordinate value="300"/>',
+            '      <YCoordinate value="-20"/>',
+            "    </LigatureAnchor>",
+            '    <LigatureAnchor index="2" empty="1"/>',
+            "  </ComponentRecord>",
+            "</LigatureAttach>",
+        ]
 
     def test_buildLigatureAttach_emptyComponents(self):
         attach = builder.buildLigatureAttach([[], None])
-        self.assertEqual(getXML(attach.toXML),
-                         ['<LigatureAttach>',
-                          '  <!-- ComponentCount=2 -->',
-                          '  <ComponentRecord index="0" empty="1"/>',
-                          '  <ComponentRecord index="1" empty="1"/>',
-                          '</LigatureAttach>'])
+        assert getXML(attach.toXML) == [
+            "<LigatureAttach>",
+            "  <!-- ComponentCount=2 -->",
+            '  <ComponentRecord index="0" empty="1"/>',
+            '  <ComponentRecord index="1" empty="1"/>',
+            "</LigatureAttach>",
+        ]
 
     def test_buildLigatureAttach_noComponents(self):
         attach = builder.buildLigatureAttach([])
-        self.assertEqual(getXML(attach.toXML),
-                         ['<LigatureAttach>',
-                          '  <!-- ComponentCount=0 -->',
-                          '</LigatureAttach>'])
+        assert getXML(attach.toXML) == [
+            "<LigatureAttach>",
+            "  <!-- ComponentCount=0 -->",
+            "</LigatureAttach>",
+        ]
 
     def test_buildLigCaretList(self):
         carets = builder.buildLigCaretList(
-            {"f_f_i": [300, 600]}, {"c_t": [42]}, self.GLYPHMAP)
-        self.assertEqual(getXML(carets.toXML),
-                         ['<LigCaretList>',
-                          '  <Coverage>',
-                          '    <Glyph value="f_f_i"/>',
-                          '    <Glyph value="c_t"/>',
-                          '  </Coverage>',
-                          '  <!-- LigGlyphCount=2 -->',
-                          '  <LigGlyph index="0">',
-                          '    <!-- CaretCount=2 -->',
-                          '    <CaretValue index="0" Format="1">',
-                          '      <Coordinate value="300"/>',
-                          '    </CaretValue>',
-                          '    <CaretValue index="1" Format="1">',
-                          '      <Coordinate value="600"/>',
-                          '    </CaretValue>',
-                          '  </LigGlyph>',
-                          '  <LigGlyph index="1">',
-                          '    <!-- CaretCount=1 -->',
-                          '    <CaretValue index="0" Format="2">',
-                          '      <CaretValuePoint value="42"/>',
-                          '    </CaretValue>',
-                          '  </LigGlyph>',
-                          '</LigCaretList>'])
+            {"f_f_i": [300, 600]}, {"c_t": [42]}, self.GLYPHMAP
+        )
+        assert getXML(carets.toXML) == [
+            "<LigCaretList>",
+            "  <Coverage>",
+            '    <Glyph value="f_f_i"/>',
+            '    <Glyph value="c_t"/>',
+            "  </Coverage>",
+            "  <!-- LigGlyphCount=2 -->",
+            '  <LigGlyph index="0">',
+            "    <!-- CaretCount=2 -->",
+            '    <CaretValue index="0" Format="1">',
+            '      <Coordinate value="300"/>',
+            "    </CaretValue>",
+            '    <CaretValue index="1" Format="1">',
+            '      <Coordinate value="600"/>',
+            "    </CaretValue>",
+            "  </LigGlyph>",
+            '  <LigGlyph index="1">',
+            "    <!-- CaretCount=1 -->",
+            '    <CaretValue index="0" Format="2">',
+            '      <CaretValuePoint value="42"/>',
+            "    </CaretValue>",
+            "  </LigGlyph>",
+            "</LigCaretList>",
+        ]
 
     def test_buildLigCaretList_bothCoordsAndPointsForSameGlyph(self):
         carets = builder.buildLigCaretList(
-            {"f_f_i": [300]}, {"f_f_i": [7]}, self.GLYPHMAP)
-        self.assertEqual(getXML(carets.toXML),
-                         ['<LigCaretList>',
-                          '  <Coverage>',
-                          '    <Glyph value="f_f_i"/>',
-                          '  </Coverage>',
-                          '  <!-- LigGlyphCount=1 -->',
-                          '  <LigGlyph index="0">',
-                          '    <!-- CaretCount=2 -->',
-                          '    <CaretValue index="0" Format="1">',
-                          '      <Coordinate value="300"/>',
-                          '    </CaretValue>',
-                          '    <CaretValue index="1" Format="2">',
-                          '      <CaretValuePoint value="7"/>',
-                          '    </CaretValue>',
-                          '  </LigGlyph>',
-                          '</LigCaretList>'])
+            {"f_f_i": [300]}, {"f_f_i": [7]}, self.GLYPHMAP
+        )
+        assert getXML(carets.toXML) == [
+            "<LigCaretList>",
+            "  <Coverage>",
+            '    <Glyph value="f_f_i"/>',
+            "  </Coverage>",
+            "  <!-- LigGlyphCount=1 -->",
+            '  <LigGlyph index="0">',
+            "    <!-- CaretCount=2 -->",
+            '    <CaretValue index="0" Format="1">',
+            '      <Coordinate value="300"/>',
+            "    </CaretValue>",
+            '    <CaretValue index="1" Format="2">',
+            '      <CaretValuePoint value="7"/>',
+            "    </CaretValue>",
+            "  </LigGlyph>",
+            "</LigCaretList>",
+        ]
 
     def test_buildLigCaretList_empty(self):
-        self.assertIsNone(builder.buildLigCaretList({}, {}, self.GLYPHMAP))
+        assert builder.buildLigCaretList({}, {}, self.GLYPHMAP) is None
 
     def test_buildLigCaretList_None(self):
-        self.assertIsNone(builder.buildLigCaretList(None, None, self.GLYPHMAP))
+        assert builder.buildLigCaretList(None, None, self.GLYPHMAP) is None
 
     def test_buildLigGlyph_coords(self):
         lig = builder.buildLigGlyph([500, 800], None)
-        self.assertEqual(getXML(lig.toXML),
-                         ['<LigGlyph>',
-                          '  <!-- CaretCount=2 -->',
-                          '  <CaretValue index="0" Format="1">',
-                          '    <Coordinate value="500"/>',
-                          '  </CaretValue>',
-                          '  <CaretValue index="1" Format="1">',
-                          '    <Coordinate value="800"/>',
-                          '  </CaretValue>',
-                          '</LigGlyph>'])
+        assert getXML(lig.toXML) == [
+            "<LigGlyph>",
+            "  <!-- CaretCount=2 -->",
+            '  <CaretValue index="0" Format="1">',
+            '    <Coordinate value="500"/>',
+            "  </CaretValue>",
+            '  <CaretValue index="1" Format="1">',
+            '    <Coordinate value="800"/>',
+            "  </CaretValue>",
+            "</LigGlyph>",
+        ]
 
     def test_buildLigGlyph_empty(self):
-        self.assertIsNone(builder.buildLigGlyph([], []))
+        assert builder.buildLigGlyph([], []) is None
 
     def test_buildLigGlyph_None(self):
-        self.assertIsNone(builder.buildLigGlyph(None, None))
+        assert builder.buildLigGlyph(None, None) is None
 
     def test_buildLigGlyph_points(self):
         lig = builder.buildLigGlyph(None, [2])
-        self.assertEqual(getXML(lig.toXML),
-                         ['<LigGlyph>',
-                          '  <!-- CaretCount=1 -->',
-                          '  <CaretValue index="0" Format="2">',
-                          '    <CaretValuePoint value="2"/>',
-                          '  </CaretValue>',
-                          '</LigGlyph>'])
+        assert getXML(lig.toXML) == [
+            "<LigGlyph>",
+            "  <!-- CaretCount=1 -->",
+            '  <CaretValue index="0" Format="2">',
+            '    <CaretValuePoint value="2"/>',
+            "  </CaretValue>",
+            "</LigGlyph>",
+        ]
 
     def test_buildLookup(self):
         s1 = builder.buildSingleSubstSubtable({"one": "two"})
         s2 = builder.buildSingleSubstSubtable({"three": "four"})
         lookup = builder.buildLookup([s1, s2], flags=7)
-        self.assertEqual(getXML(lookup.toXML),
-                         ['<Lookup>',
-                          '  <LookupType value="1"/>',
-                          '  <LookupFlag value="7"/>',
-                          '  <!-- SubTableCount=2 -->',
-                          '  <SingleSubst index="0">',
-                          '    <Substitution in="one" out="two"/>',
-                          '  </SingleSubst>',
-                          '  <SingleSubst index="1">',
-                          '    <Substitution in="three" out="four"/>',
-                          '  </SingleSubst>',
-                          '</Lookup>'])
+        assert getXML(lookup.toXML) == [
+            "<Lookup>",
+            '  <LookupType value="1"/>',
+            '  <LookupFlag value="7"/>',
+            "  <!-- SubTableCount=2 -->",
+            '  <SingleSubst index="0">',
+            '    <Substitution in="one" out="two"/>',
+            "  </SingleSubst>",
+            '  <SingleSubst index="1">',
+            '    <Substitution in="three" out="four"/>',
+            "  </SingleSubst>",
+            "</Lookup>",
+        ]
 
     def test_buildLookup_badFlags(self):
         s = builder.buildSingleSubstSubtable({"one": "two"})
-        self.assertRaisesRegex(
-            AssertionError, "if markFilterSet is None, "
-            "flags must not set LOOKUP_FLAG_USE_MARK_FILTERING_SET; "
-            "flags=0x0010",
-            builder.buildLookup, [s],
-            builder.LOOKUP_FLAG_USE_MARK_FILTERING_SET, None)
-        self.assertRaisesRegex(
-            AssertionError, "if markFilterSet is not None, "
-            "flags must set LOOKUP_FLAG_USE_MARK_FILTERING_SET; "
-            "flags=0x0004",
-            builder.buildLookup, [s],
-            builder.LOOKUP_FLAG_IGNORE_LIGATURES, 777)
+        with pytest.raises(
+            AssertionError,
+            match=(
+                "if markFilterSet is None, flags must not set "
+                "LOOKUP_FLAG_USE_MARK_FILTERING_SET; flags=0x0010"
+            ),
+        ) as excinfo:
+            builder.buildLookup([s], builder.LOOKUP_FLAG_USE_MARK_FILTERING_SET, None)
+        with pytest.raises(
+            AssertionError,
+            match=(
+                "if markFilterSet is not None, flags must set "
+                "LOOKUP_FLAG_USE_MARK_FILTERING_SET; flags=0x0004"
+            ),
+        ) as excinfo:
+            builder.buildLookup([s], builder.LOOKUP_FLAG_IGNORE_LIGATURES, 777)
 
     def test_buildLookup_conflictingSubtableTypes(self):
         s1 = builder.buildSingleSubstSubtable({"one": "two"})
         s2 = builder.buildAlternateSubstSubtable({"one": ["two", "three"]})
-        self.assertRaisesRegex(
-            AssertionError, "all subtables must have the same LookupType",
-            builder.buildLookup, [s1, s2])
+        with pytest.raises(
+            AssertionError, match="all subtables must have the same LookupType"
+        ) as excinfo:
+            builder.buildLookup([s1, s2])
 
     def test_buildLookup_noSubtables(self):
-        self.assertIsNone(builder.buildLookup([]))
-        self.assertIsNone(builder.buildLookup(None))
-        self.assertIsNone(builder.buildLookup([None]))
-        self.assertIsNone(builder.buildLookup([None, None]))
+        assert builder.buildLookup([]) is None
+        assert builder.buildLookup(None) is None
+        assert builder.buildLookup([None]) is None
+        assert builder.buildLookup([None, None]) is None
 
     def test_buildLookup_markFilterSet(self):
         s = builder.buildSingleSubstSubtable({"one": "two"})
-        flags = (builder.LOOKUP_FLAG_RIGHT_TO_LEFT |
-                 builder.LOOKUP_FLAG_USE_MARK_FILTERING_SET)
+        flags = (
+            builder.LOOKUP_FLAG_RIGHT_TO_LEFT
+            | builder.LOOKUP_FLAG_USE_MARK_FILTERING_SET
+        )
         lookup = builder.buildLookup([s], flags, markFilterSet=999)
-        self.assertEqual(getXML(lookup.toXML),
-                         ['<Lookup>',
-                          '  <LookupType value="1"/>',
-                          '  <LookupFlag value="17"/>',
-                          '  <!-- SubTableCount=1 -->',
-                          '  <SingleSubst index="0">',
-                          '    <Substitution in="one" out="two"/>',
-                          '  </SingleSubst>',
-                          '  <MarkFilteringSet value="999"/>',
-                          '</Lookup>'])
+        assert getXML(lookup.toXML) == [
+            "<Lookup>",
+            '  <LookupType value="1"/>',
+            '  <LookupFlag value="17"/>',
+            "  <!-- SubTableCount=1 -->",
+            '  <SingleSubst index="0">',
+            '    <Substitution in="one" out="two"/>',
+            "  </SingleSubst>",
+            '  <MarkFilteringSet value="999"/>',
+            "</Lookup>",
+        ]
 
     def test_buildMarkArray(self):
-        markArray = builder.buildMarkArray({
-            "acute": (7, builder.buildAnchor(300, 800)),
-            "grave": (2, builder.buildAnchor(10, 80))
-        }, self.GLYPHMAP)
-        self.assertLess(self.GLYPHMAP["grave"], self.GLYPHMAP["acute"])
-        self.assertEqual(getXML(markArray.toXML),
-                         ['<MarkArray>',
-                          '  <!-- MarkCount=2 -->',
-                          '  <MarkRecord index="0">',
-                          '    <Class value="2"/>',
-                          '    <MarkAnchor Format="1">',
-                          '      <XCoordinate value="10"/>',
-                          '      <YCoordinate value="80"/>',
-                          '    </MarkAnchor>',
-                          '  </MarkRecord>',
-                          '  <MarkRecord index="1">',
-                          '    <Class value="7"/>',
-                          '    <MarkAnchor Format="1">',
-                          '      <XCoordinate value="300"/>',
-                          '      <YCoordinate value="800"/>',
-                          '    </MarkAnchor>',
-                          '  </MarkRecord>',
-                          '</MarkArray>'])
+        markArray = builder.buildMarkArray(
+            {
+                "acute": (7, builder.buildAnchor(300, 800)),
+                "grave": (2, builder.buildAnchor(10, 80)),
+            },
+            self.GLYPHMAP,
+        )
+        assert self.GLYPHMAP["grave"] < self.GLYPHMAP["acute"]
+        assert getXML(markArray.toXML) == [
+            "<MarkArray>",
+            "  <!-- MarkCount=2 -->",
+            '  <MarkRecord index="0">',
+            '    <Class value="2"/>',
+            '    <MarkAnchor Format="1">',
+            '      <XCoordinate value="10"/>',
+            '      <YCoordinate value="80"/>',
+            "    </MarkAnchor>",
+            "  </MarkRecord>",
+            '  <MarkRecord index="1">',
+            '    <Class value="7"/>',
+            '    <MarkAnchor Format="1">',
+            '      <XCoordinate value="300"/>',
+            '      <YCoordinate value="800"/>',
+            "    </MarkAnchor>",
+            "  </MarkRecord>",
+            "</MarkArray>",
+        ]
 
     def test_buildMarkBasePosSubtable(self):
         anchor = builder.buildAnchor
         marks = {
             "acute": (0, anchor(300, 700)),
             "cedilla": (1, anchor(300, -100)),
-            "grave": (0, anchor(300, 700))
+            "grave": (0, anchor(300, 700)),
         }
         bases = {
             # Make sure we can handle missing entries.
             "A": {},  # no entry for any markClass
             "B": {0: anchor(500, 900)},  # only markClass 0 specified
             "C": {1: anchor(500, -10)},  # only markClass 1 specified
-
             "a": {0: anchor(500, 400), 1: anchor(500, -20)},
-            "b": {0: anchor(500, 800), 1: anchor(500, -20)}
+            "b": {0: anchor(500, 800), 1: anchor(500, -20)},
         }
         table = builder.buildMarkBasePosSubtable(marks, bases, self.GLYPHMAP)
-        self.assertEqual(getXML(table.toXML),
-                         ['<MarkBasePos Format="1">',
-                          '  <MarkCoverage>',
-                          '    <Glyph value="grave"/>',
-                          '    <Glyph value="acute"/>',
-                          '    <Glyph value="cedilla"/>',
-                          '  </MarkCoverage>',
-                          '  <BaseCoverage>',
-                          '    <Glyph value="A"/>',
-                          '    <Glyph value="B"/>',
-                          '    <Glyph value="C"/>',
-                          '    <Glyph value="a"/>',
-                          '    <Glyph value="b"/>',
-                          '  </BaseCoverage>',
-                          '  <!-- ClassCount=2 -->',
-                          '  <MarkArray>',
-                          '    <!-- MarkCount=3 -->',
-                          '    <MarkRecord index="0">',  # grave
-                          '      <Class value="0"/>',
-                          '      <MarkAnchor Format="1">',
-                          '        <XCoordinate value="300"/>',
-                          '        <YCoordinate value="700"/>',
-                          '      </MarkAnchor>',
-                          '    </MarkRecord>',
-                          '    <MarkRecord index="1">',  # acute
-                          '      <Class value="0"/>',
-                          '      <MarkAnchor Format="1">',
-                          '        <XCoordinate value="300"/>',
-                          '        <YCoordinate value="700"/>',
-                          '      </MarkAnchor>',
-                          '    </MarkRecord>',
-                          '    <MarkRecord index="2">',  # cedilla
-                          '      <Class value="1"/>',
-                          '      <MarkAnchor Format="1">',
-                          '        <XCoordinate value="300"/>',
-                          '        <YCoordinate value="-100"/>',
-                          '      </MarkAnchor>',
-                          '    </MarkRecord>',
-                          '  </MarkArray>',
-                          '  <BaseArray>',
-                          '    <!-- BaseCount=5 -->',
-                          '    <BaseRecord index="0">',  # A
-                          '      <BaseAnchor index="0" empty="1"/>',
-                          '      <BaseAnchor index="1" empty="1"/>',
-                          '    </BaseRecord>',
-                          '    <BaseRecord index="1">',  # B
-                          '      <BaseAnchor index="0" Format="1">',
-                          '        <XCoordinate value="500"/>',
-                          '        <YCoordinate value="900"/>',
-                          '      </BaseAnchor>',
-                          '      <BaseAnchor index="1" empty="1"/>',
-                          '    </BaseRecord>',
-                          '    <BaseRecord index="2">',  # C
-                          '      <BaseAnchor index="0" empty="1"/>',
-                          '      <BaseAnchor index="1" Format="1">',
-                          '        <XCoordinate value="500"/>',
-                          '        <YCoordinate value="-10"/>',
-                          '      </BaseAnchor>',
-                          '    </BaseRecord>',
-                          '    <BaseRecord index="3">',  # a
-                          '      <BaseAnchor index="0" Format="1">',
-                          '        <XCoordinate value="500"/>',
-                          '        <YCoordinate value="400"/>',
-                          '      </BaseAnchor>',
-                          '      <BaseAnchor index="1" Format="1">',
-                          '        <XCoordinate value="500"/>',
-                          '        <YCoordinate value="-20"/>',
-                          '      </BaseAnchor>',
-                          '    </BaseRecord>',
-                          '    <BaseRecord index="4">',  # b
-                          '      <BaseAnchor index="0" Format="1">',
-                          '        <XCoordinate value="500"/>',
-                          '        <YCoordinate value="800"/>',
-                          '      </BaseAnchor>',
-                          '      <BaseAnchor index="1" Format="1">',
-                          '        <XCoordinate value="500"/>',
-                          '        <YCoordinate value="-20"/>',
-                          '      </BaseAnchor>',
-                          '    </BaseRecord>',
-                          '  </BaseArray>',
-                          '</MarkBasePos>'])
+        assert getXML(table.toXML) == [
+            '<MarkBasePos Format="1">',
+            "  <MarkCoverage>",
+            '    <Glyph value="grave"/>',
+            '    <Glyph value="acute"/>',
+            '    <Glyph value="cedilla"/>',
+            "  </MarkCoverage>",
+            "  <BaseCoverage>",
+            '    <Glyph value="A"/>',
+            '    <Glyph value="B"/>',
+            '    <Glyph value="C"/>',
+            '    <Glyph value="a"/>',
+            '    <Glyph value="b"/>',
+            "  </BaseCoverage>",
+            "  <!-- ClassCount=2 -->",
+            "  <MarkArray>",
+            "    <!-- MarkCount=3 -->",
+            '    <MarkRecord index="0">',  # grave
+            '      <Class value="0"/>',
+            '      <MarkAnchor Format="1">',
+            '        <XCoordinate value="300"/>',
+            '        <YCoordinate value="700"/>',
+            "      </MarkAnchor>",
+            "    </MarkRecord>",
+            '    <MarkRecord index="1">',  # acute
+            '      <Class value="0"/>',
+            '      <MarkAnchor Format="1">',
+            '        <XCoordinate value="300"/>',
+            '        <YCoordinate value="700"/>',
+            "      </MarkAnchor>",
+            "    </MarkRecord>",
+            '    <MarkRecord index="2">',  # cedilla
+            '      <Class value="1"/>',
+            '      <MarkAnchor Format="1">',
+            '        <XCoordinate value="300"/>',
+            '        <YCoordinate value="-100"/>',
+            "      </MarkAnchor>",
+            "    </MarkRecord>",
+            "  </MarkArray>",
+            "  <BaseArray>",
+            "    <!-- BaseCount=5 -->",
+            '    <BaseRecord index="0">',  # A
+            '      <BaseAnchor index="0" empty="1"/>',
+            '      <BaseAnchor index="1" empty="1"/>',
+            "    </BaseRecord>",
+            '    <BaseRecord index="1">',  # B
+            '      <BaseAnchor index="0" Format="1">',
+            '        <XCoordinate value="500"/>',
+            '        <YCoordinate value="900"/>',
+            "      </BaseAnchor>",
+            '      <BaseAnchor index="1" empty="1"/>',
+            "    </BaseRecord>",
+            '    <BaseRecord index="2">',  # C
+            '      <BaseAnchor index="0" empty="1"/>',
+            '      <BaseAnchor index="1" Format="1">',
+            '        <XCoordinate value="500"/>',
+            '        <YCoordinate value="-10"/>',
+            "      </BaseAnchor>",
+            "    </BaseRecord>",
+            '    <BaseRecord index="3">',  # a
+            '      <BaseAnchor index="0" Format="1">',
+            '        <XCoordinate value="500"/>',
+            '        <YCoordinate value="400"/>',
+            "      </BaseAnchor>",
+            '      <BaseAnchor index="1" Format="1">',
+            '        <XCoordinate value="500"/>',
+            '        <YCoordinate value="-20"/>',
+            "      </BaseAnchor>",
+            "    </BaseRecord>",
+            '    <BaseRecord index="4">',  # b
+            '      <BaseAnchor index="0" Format="1">',
+            '        <XCoordinate value="500"/>',
+            '        <YCoordinate value="800"/>',
+            "      </BaseAnchor>",
+            '      <BaseAnchor index="1" Format="1">',
+            '        <XCoordinate value="500"/>',
+            '        <YCoordinate value="-20"/>',
+            "      </BaseAnchor>",
+            "    </BaseRecord>",
+            "  </BaseArray>",
+            "</MarkBasePos>",
+        ]
 
     def test_buildMarkGlyphSetsDef(self):
         marksets = builder.buildMarkGlyphSetsDef(
-            [{"acute", "grave"}, {"cedilla", "grave"}], self.GLYPHMAP)
-        self.assertEqual(getXML(marksets.toXML),
-                         ['<MarkGlyphSetsDef>',
-                          '  <MarkSetTableFormat value="1"/>',
-                          '  <!-- MarkSetCount=2 -->',
-                          '  <Coverage index="0">',
-                          '    <Glyph value="grave"/>',
-                          '    <Glyph value="acute"/>',
-                          '  </Coverage>',
-                          '  <Coverage index="1">',
-                          '    <Glyph value="grave"/>',
-                          '    <Glyph value="cedilla"/>',
-                          '  </Coverage>',
-                          '</MarkGlyphSetsDef>'])
+            [{"acute", "grave"}, {"cedilla", "grave"}], self.GLYPHMAP
+        )
+        assert getXML(marksets.toXML) == [
+            "<MarkGlyphSetsDef>",
+            '  <MarkSetTableFormat value="1"/>',
+            "  <!-- MarkSetCount=2 -->",
+            '  <Coverage index="0">',
+            '    <Glyph value="grave"/>',
+            '    <Glyph value="acute"/>',
+            "  </Coverage>",
+            '  <Coverage index="1">',
+            '    <Glyph value="grave"/>',
+            '    <Glyph value="cedilla"/>',
+            "  </Coverage>",
+            "</MarkGlyphSetsDef>",
+        ]
 
     def test_buildMarkGlyphSetsDef_empty(self):
-        self.assertIsNone(builder.buildMarkGlyphSetsDef([], self.GLYPHMAP))
+        assert builder.buildMarkGlyphSetsDef([], self.GLYPHMAP) is None
 
     def test_buildMarkGlyphSetsDef_None(self):
-        self.assertIsNone(builder.buildMarkGlyphSetsDef(None, self.GLYPHMAP))
+        assert builder.buildMarkGlyphSetsDef(None, self.GLYPHMAP) is None
 
     def test_buildMarkLigPosSubtable(self):
         anchor = builder.buildAnchor
         marks = {
             "acute": (0, anchor(300, 700)),
             "cedilla": (1, anchor(300, -100)),
-            "grave": (0, anchor(300, 700))
+            "grave": (0, anchor(300, 700)),
         }
         bases = {
             "f_i": [{}, {0: anchor(200, 400)}],  # nothing on f; only 1 on i
             "c_t": [
-                {0: anchor(500, 600), 1: anchor(500, -20)},   # c
-                {0: anchor(1300, 800), 1: anchor(1300, -20)}  # t
-            ]
+                {0: anchor(500, 600), 1: anchor(500, -20)},  # c
+                {0: anchor(1300, 800), 1: anchor(1300, -20)},  # t
+            ],
         }
         table = builder.buildMarkLigPosSubtable(marks, bases, self.GLYPHMAP)
-        self.assertEqual(getXML(table.toXML),
-                         ['<MarkLigPos Format="1">',
-                          '  <MarkCoverage>',
-                          '    <Glyph value="grave"/>',
-                          '    <Glyph value="acute"/>',
-                          '    <Glyph value="cedilla"/>',
-                          '  </MarkCoverage>',
-                          '  <LigatureCoverage>',
-                          '    <Glyph value="f_i"/>',
-                          '    <Glyph value="c_t"/>',
-                          '  </LigatureCoverage>',
-                          '  <!-- ClassCount=2 -->',
-                          '  <MarkArray>',
-                          '    <!-- MarkCount=3 -->',
-                          '    <MarkRecord index="0">',
-                          '      <Class value="0"/>',
-                          '      <MarkAnchor Format="1">',
-                          '        <XCoordinate value="300"/>',
-                          '        <YCoordinate value="700"/>',
-                          '      </MarkAnchor>',
-                          '    </MarkRecord>',
-                          '    <MarkRecord index="1">',
-                          '      <Class value="0"/>',
-                          '      <MarkAnchor Format="1">',
-                          '        <XCoordinate value="300"/>',
-                          '        <YCoordinate value="700"/>',
-                          '      </MarkAnchor>',
-                          '    </MarkRecord>',
-                          '    <MarkRecord index="2">',
-                          '      <Class value="1"/>',
-                          '      <MarkAnchor Format="1">',
-                          '        <XCoordinate value="300"/>',
-                          '        <YCoordinate value="-100"/>',
-                          '      </MarkAnchor>',
-                          '    </MarkRecord>',
-                          '  </MarkArray>',
-                          '  <LigatureArray>',
-                          '    <!-- LigatureCount=2 -->',
-                          '    <LigatureAttach index="0">',
-                          '      <!-- ComponentCount=2 -->',
-                          '      <ComponentRecord index="0">',
-                          '        <LigatureAnchor index="0" empty="1"/>',
-                          '        <LigatureAnchor index="1" empty="1"/>',
-                          '      </ComponentRecord>',
-                          '      <ComponentRecord index="1">',
-                          '        <LigatureAnchor index="0" Format="1">',
-                          '          <XCoordinate value="200"/>',
-                          '          <YCoordinate value="400"/>',
-                          '        </LigatureAnchor>',
-                          '        <LigatureAnchor index="1" empty="1"/>',
-                          '      </ComponentRecord>',
-                          '    </LigatureAttach>',
-                          '    <LigatureAttach index="1">',
-                          '      <!-- ComponentCount=2 -->',
-                          '      <ComponentRecord index="0">',
-                          '        <LigatureAnchor index="0" Format="1">',
-                          '          <XCoordinate value="500"/>',
-                          '          <YCoordinate value="600"/>',
-                          '        </LigatureAnchor>',
-                          '        <LigatureAnchor index="1" Format="1">',
-                          '          <XCoordinate value="500"/>',
-                          '          <YCoordinate value="-20"/>',
-                          '        </LigatureAnchor>',
-                          '      </ComponentRecord>',
-                          '      <ComponentRecord index="1">',
-                          '        <LigatureAnchor index="0" Format="1">',
-                          '          <XCoordinate value="1300"/>',
-                          '          <YCoordinate value="800"/>',
-                          '        </LigatureAnchor>',
-                          '        <LigatureAnchor index="1" Format="1">',
-                          '          <XCoordinate value="1300"/>',
-                          '          <YCoordinate value="-20"/>',
-                          '        </LigatureAnchor>',
-                          '      </ComponentRecord>',
-                          '    </LigatureAttach>',
-                          '  </LigatureArray>',
-                          '</MarkLigPos>'])
+        assert getXML(table.toXML) == [
+            '<MarkLigPos Format="1">',
+            "  <MarkCoverage>",
+            '    <Glyph value="grave"/>',
+            '    <Glyph value="acute"/>',
+            '    <Glyph value="cedilla"/>',
+            "  </MarkCoverage>",
+            "  <LigatureCoverage>",
+            '    <Glyph value="f_i"/>',
+            '    <Glyph value="c_t"/>',
+            "  </LigatureCoverage>",
+            "  <!-- ClassCount=2 -->",
+            "  <MarkArray>",
+            "    <!-- MarkCount=3 -->",
+            '    <MarkRecord index="0">',
+            '      <Class value="0"/>',
+            '      <MarkAnchor Format="1">',
+            '        <XCoordinate value="300"/>',
+            '        <YCoordinate value="700"/>',
+            "      </MarkAnchor>",
+            "    </MarkRecord>",
+            '    <MarkRecord index="1">',
+            '      <Class value="0"/>',
+            '      <MarkAnchor Format="1">',
+            '        <XCoordinate value="300"/>',
+            '        <YCoordinate value="700"/>',
+            "      </MarkAnchor>",
+            "    </MarkRecord>",
+            '    <MarkRecord index="2">',
+            '      <Class value="1"/>',
+            '      <MarkAnchor Format="1">',
+            '        <XCoordinate value="300"/>',
+            '        <YCoordinate value="-100"/>',
+            "      </MarkAnchor>",
+            "    </MarkRecord>",
+            "  </MarkArray>",
+            "  <LigatureArray>",
+            "    <!-- LigatureCount=2 -->",
+            '    <LigatureAttach index="0">',
+            "      <!-- ComponentCount=2 -->",
+            '      <ComponentRecord index="0">',
+            '        <LigatureAnchor index="0" empty="1"/>',
+            '        <LigatureAnchor index="1" empty="1"/>',
+            "      </ComponentRecord>",
+            '      <ComponentRecord index="1">',
+            '        <LigatureAnchor index="0" Format="1">',
+            '          <XCoordinate value="200"/>',
+            '          <YCoordinate value="400"/>',
+            "        </LigatureAnchor>",
+            '        <LigatureAnchor index="1" empty="1"/>',
+            "      </ComponentRecord>",
+            "    </LigatureAttach>",
+            '    <LigatureAttach index="1">',
+            "      <!-- ComponentCount=2 -->",
+            '      <ComponentRecord index="0">',
+            '        <LigatureAnchor index="0" Format="1">',
+            '          <XCoordinate value="500"/>',
+            '          <YCoordinate value="600"/>',
+            "        </LigatureAnchor>",
+            '        <LigatureAnchor index="1" Format="1">',
+            '          <XCoordinate value="500"/>',
+            '          <YCoordinate value="-20"/>',
+            "        </LigatureAnchor>",
+            "      </ComponentRecord>",
+            '      <ComponentRecord index="1">',
+            '        <LigatureAnchor index="0" Format="1">',
+            '          <XCoordinate value="1300"/>',
+            '          <YCoordinate value="800"/>',
+            "        </LigatureAnchor>",
+            '        <LigatureAnchor index="1" Format="1">',
+            '          <XCoordinate value="1300"/>',
+            '          <YCoordinate value="-20"/>',
+            "        </LigatureAnchor>",
+            "      </ComponentRecord>",
+            "    </LigatureAttach>",
+            "  </LigatureArray>",
+            "</MarkLigPos>",
+        ]
 
     def test_buildMarkRecord(self):
         rec = builder.buildMarkRecord(17, builder.buildAnchor(500, -20))
-        self.assertEqual(getXML(rec.toXML),
-                         ['<MarkRecord>',
-                          '  <Class value="17"/>',
-                          '  <MarkAnchor Format="1">',
-                          '    <XCoordinate value="500"/>',
-                          '    <YCoordinate value="-20"/>',
-                          '  </MarkAnchor>',
-                          '</MarkRecord>'])
+        assert getXML(rec.toXML) == [
+            "<MarkRecord>",
+            '  <Class value="17"/>',
+            '  <MarkAnchor Format="1">',
+            '    <XCoordinate value="500"/>',
+            '    <YCoordinate value="-20"/>',
+            "  </MarkAnchor>",
+            "</MarkRecord>",
+        ]
 
     def test_buildMark2Record(self):
         a = builder.buildAnchor
         rec = builder.buildMark2Record([a(500, -20), None, a(300, -15)])
-        self.assertEqual(getXML(rec.toXML),
-                         ['<Mark2Record>',
-                          '  <Mark2Anchor index="0" Format="1">',
-                          '    <XCoordinate value="500"/>',
-                          '    <YCoordinate value="-20"/>',
-                          '  </Mark2Anchor>',
-                          '  <Mark2Anchor index="1" empty="1"/>',
-                          '  <Mark2Anchor index="2" Format="1">',
-                          '    <XCoordinate value="300"/>',
-                          '    <YCoordinate value="-15"/>',
-                          '  </Mark2Anchor>',
-                          '</Mark2Record>'])
+        assert getXML(rec.toXML) == [
+            "<Mark2Record>",
+            '  <Mark2Anchor index="0" Format="1">',
+            '    <XCoordinate value="500"/>',
+            '    <YCoordinate value="-20"/>',
+            "  </Mark2Anchor>",
+            '  <Mark2Anchor index="1" empty="1"/>',
+            '  <Mark2Anchor index="2" Format="1">',
+            '    <XCoordinate value="300"/>',
+            '    <YCoordinate value="-15"/>',
+            "  </Mark2Anchor>",
+            "</Mark2Record>",
+        ]
 
     def test_buildPairPosClassesSubtable(self):
         d20 = builder.buildValue({"XPlacement": -20})
         d50 = builder.buildValue({"XPlacement": -50})
         d0 = builder.buildValue({})
         d8020 = builder.buildValue({"XPlacement": -80, "YPlacement": -20})
-        subtable = builder.buildPairPosClassesSubtable({
-            (tuple("A",), tuple(["zero"])): (d0, d50),
-            (tuple("A",), tuple(["one", "two"])):  (None, d20),
-            (tuple(["B", "C"]), tuple(["zero"])): (d8020, d50),
-        }, self.GLYPHMAP)
-        self.assertEqual(getXML(subtable.toXML),
-                         ['<PairPos Format="2">',
-                          '  <Coverage>',
-                          '    <Glyph value="A"/>',
-                          '    <Glyph value="B"/>',
-                          '    <Glyph value="C"/>',
-                          '  </Coverage>',
-                          '  <ValueFormat1 value="3"/>',
-                          '  <ValueFormat2 value="1"/>',
-                          '  <ClassDef1>',
-                          '    <ClassDef glyph="A" class="1"/>',
-                          '  </ClassDef1>',
-                          '  <ClassDef2>',
-                          '    <ClassDef glyph="one" class="1"/>',
-                          '    <ClassDef glyph="two" class="1"/>',
-                          '    <ClassDef glyph="zero" class="2"/>',
-                          '  </ClassDef2>',
-                          '  <!-- Class1Count=2 -->',
-                          '  <!-- Class2Count=3 -->',
-                          '  <Class1Record index="0">',
-                          '    <Class2Record index="0">',
-                          '    </Class2Record>',
-                          '    <Class2Record index="1">',
-                          '    </Class2Record>',
-                          '    <Class2Record index="2">',
-                          '      <Value1 XPlacement="-80" YPlacement="-20"/>',
-                          '      <Value2 XPlacement="-50"/>',
-                          '    </Class2Record>',
-                          '  </Class1Record>',
-                          '  <Class1Record index="1">',
-                          '    <Class2Record index="0">',
-                          '    </Class2Record>',
-                          '    <Class2Record index="1">',
-                          '      <Value2 XPlacement="-20"/>',
-                          '    </Class2Record>',
-                          '    <Class2Record index="2">',
-                          '      <Value1/>',
-                          '      <Value2 XPlacement="-50"/>',
-                          '    </Class2Record>',
-                          '  </Class1Record>',
-                          '</PairPos>'])
+        subtable = builder.buildPairPosClassesSubtable(
+            {
+                (tuple("A"), tuple(["zero"])): (d0, d50),
+                (tuple("A"), tuple(["one", "two"])): (None, d20),
+                (tuple(["B", "C"]), tuple(["zero"])): (d8020, d50),
+            },
+            self.GLYPHMAP,
+        )
+        assert getXML(subtable.toXML) == [
+            '<PairPos Format="2">',
+            "  <Coverage>",
+            '    <Glyph value="A"/>',
+            '    <Glyph value="B"/>',
+            '    <Glyph value="C"/>',
+            "  </Coverage>",
+            '  <ValueFormat1 value="3"/>',
+            '  <ValueFormat2 value="1"/>',
+            "  <ClassDef1>",
+            '    <ClassDef glyph="A" class="1"/>',
+            "  </ClassDef1>",
+            "  <ClassDef2>",
+            '    <ClassDef glyph="one" class="1"/>',
+            '    <ClassDef glyph="two" class="1"/>',
+            '    <ClassDef glyph="zero" class="2"/>',
+            "  </ClassDef2>",
+            "  <!-- Class1Count=2 -->",
+            "  <!-- Class2Count=3 -->",
+            '  <Class1Record index="0">',
+            '    <Class2Record index="0">',
+            "    </Class2Record>",
+            '    <Class2Record index="1">',
+            "    </Class2Record>",
+            '    <Class2Record index="2">',
+            '      <Value1 XPlacement="-80" YPlacement="-20"/>',
+            '      <Value2 XPlacement="-50"/>',
+            "    </Class2Record>",
+            "  </Class1Record>",
+            '  <Class1Record index="1">',
+            '    <Class2Record index="0">',
+            "    </Class2Record>",
+            '    <Class2Record index="1">',
+            '      <Value2 XPlacement="-20"/>',
+            "    </Class2Record>",
+            '    <Class2Record index="2">',
+            "      <Value1/>",
+            '      <Value2 XPlacement="-50"/>',
+            "    </Class2Record>",
+            "  </Class1Record>",
+            "</PairPos>",
+        ]
 
     def test_buildPairPosGlyphs(self):
         d50 = builder.buildValue({"XPlacement": -50})
         d8020 = builder.buildValue({"XPlacement": -80, "YPlacement": -20})
-        subtables = builder.buildPairPosGlyphs({
-            ("A", "zero"): (None, d50),
-            ("A", "one"):  (d8020, d50),
-        }, self.GLYPHMAP)
-        self.assertEqual(sum([getXML(t.toXML) for t in subtables], []),
-                         ['<PairPos Format="1">',
-                          '  <Coverage>',
-                          '    <Glyph value="A"/>',
-                          '  </Coverage>',
-                          '  <ValueFormat1 value="0"/>',
-                          '  <ValueFormat2 value="1"/>',
-                          '  <!-- PairSetCount=1 -->',
-                          '  <PairSet index="0">',
-                          '    <!-- PairValueCount=1 -->',
-                          '    <PairValueRecord index="0">',
-                          '      <SecondGlyph value="zero"/>',
-                          '      <Value2 XPlacement="-50"/>',
-                          '    </PairValueRecord>',
-                          '  </PairSet>',
-                          '</PairPos>',
-                          '<PairPos Format="1">',
-                          '  <Coverage>',
-                          '    <Glyph value="A"/>',
-                          '  </Coverage>',
-                          '  <ValueFormat1 value="3"/>',
-                          '  <ValueFormat2 value="1"/>',
-                          '  <!-- PairSetCount=1 -->',
-                          '  <PairSet index="0">',
-                          '    <!-- PairValueCount=1 -->',
-                          '    <PairValueRecord index="0">',
-                          '      <SecondGlyph value="one"/>',
-                          '      <Value1 XPlacement="-80" YPlacement="-20"/>',
-                          '      <Value2 XPlacement="-50"/>',
-                          '    </PairValueRecord>',
-                          '  </PairSet>',
-                          '</PairPos>'])
+        subtables = builder.buildPairPosGlyphs(
+            {("A", "zero"): (None, d50), ("A", "one"): (d8020, d50)}, self.GLYPHMAP
+        )
+        assert sum([getXML(t.toXML) for t in subtables], []) == [
+            '<PairPos Format="1">',
+            "  <Coverage>",
+            '    <Glyph value="A"/>',
+            "  </Coverage>",
+            '  <ValueFormat1 value="0"/>',
+            '  <ValueFormat2 value="1"/>',
+            "  <!-- PairSetCount=1 -->",
+            '  <PairSet index="0">',
+            "    <!-- PairValueCount=1 -->",
+            '    <PairValueRecord index="0">',
+            '      <SecondGlyph value="zero"/>',
+            '      <Value2 XPlacement="-50"/>',
+            "    </PairValueRecord>",
+            "  </PairSet>",
+            "</PairPos>",
+            '<PairPos Format="1">',
+            "  <Coverage>",
+            '    <Glyph value="A"/>',
+            "  </Coverage>",
+            '  <ValueFormat1 value="3"/>',
+            '  <ValueFormat2 value="1"/>',
+            "  <!-- PairSetCount=1 -->",
+            '  <PairSet index="0">',
+            "    <!-- PairValueCount=1 -->",
+            '    <PairValueRecord index="0">',
+            '      <SecondGlyph value="one"/>',
+            '      <Value1 XPlacement="-80" YPlacement="-20"/>',
+            '      <Value2 XPlacement="-50"/>',
+            "    </PairValueRecord>",
+            "  </PairSet>",
+            "</PairPos>",
+        ]
 
     def test_buildPairPosGlyphsSubtable(self):
         d20 = builder.buildValue({"XPlacement": -20})
         d50 = builder.buildValue({"XPlacement": -50})
         d0 = builder.buildValue({})
         d8020 = builder.buildValue({"XPlacement": -80, "YPlacement": -20})
-        subtable = builder.buildPairPosGlyphsSubtable({
-            ("A", "zero"): (d0, d50),
-            ("A", "one"):  (None, d20),
-            ("B", "five"): (d8020, d50),
-        }, self.GLYPHMAP)
-        self.assertEqual(getXML(subtable.toXML),
-                         ['<PairPos Format="1">',
-                          '  <Coverage>',
-                          '    <Glyph value="A"/>',
-                          '    <Glyph value="B"/>',
-                          '  </Coverage>',
-                          '  <ValueFormat1 value="3"/>',
-                          '  <ValueFormat2 value="1"/>',
-                          '  <!-- PairSetCount=2 -->',
-                          '  <PairSet index="0">',
-                          '    <!-- PairValueCount=2 -->',
-                          '    <PairValueRecord index="0">',
-                          '      <SecondGlyph value="zero"/>',
-                          '      <Value2 XPlacement="-50"/>',
-                          '    </PairValueRecord>',
-                          '    <PairValueRecord index="1">',
-                          '      <SecondGlyph value="one"/>',
-                          '      <Value2 XPlacement="-20"/>',
-                          '    </PairValueRecord>',
-                          '  </PairSet>',
-                          '  <PairSet index="1">',
-                          '    <!-- PairValueCount=1 -->',
-                          '    <PairValueRecord index="0">',
-                          '      <SecondGlyph value="five"/>',
-                          '      <Value1 XPlacement="-80" YPlacement="-20"/>',
-                          '      <Value2 XPlacement="-50"/>',
-                          '    </PairValueRecord>',
-                          '  </PairSet>',
-                          '</PairPos>'])
+        subtable = builder.buildPairPosGlyphsSubtable(
+            {
+                ("A", "zero"): (d0, d50),
+                ("A", "one"): (None, d20),
+                ("B", "five"): (d8020, d50),
+            },
+            self.GLYPHMAP,
+        )
+        assert getXML(subtable.toXML) == [
+            '<PairPos Format="1">',
+            "  <Coverage>",
+            '    <Glyph value="A"/>',
+            '    <Glyph value="B"/>',
+            "  </Coverage>",
+            '  <ValueFormat1 value="3"/>',
+            '  <ValueFormat2 value="1"/>',
+            "  <!-- PairSetCount=2 -->",
+            '  <PairSet index="0">',
+            "    <!-- PairValueCount=2 -->",
+            '    <PairValueRecord index="0">',
+            '      <SecondGlyph value="zero"/>',
+            '      <Value2 XPlacement="-50"/>',
+            "    </PairValueRecord>",
+            '    <PairValueRecord index="1">',
+            '      <SecondGlyph value="one"/>',
+            '      <Value2 XPlacement="-20"/>',
+            "    </PairValueRecord>",
+            "  </PairSet>",
+            '  <PairSet index="1">',
+            "    <!-- PairValueCount=1 -->",
+            '    <PairValueRecord index="0">',
+            '      <SecondGlyph value="five"/>',
+            '      <Value1 XPlacement="-80" YPlacement="-20"/>',
+            '      <Value2 XPlacement="-50"/>',
+            "    </PairValueRecord>",
+            "  </PairSet>",
+            "</PairPos>",
+        ]
 
     def test_buildSinglePos(self):
-        subtables = builder.buildSinglePos({
-            "one": builder.buildValue({"XPlacement": 500}),
-            "two": builder.buildValue({"XPlacement": 500}),
-            "three": builder.buildValue({"XPlacement": 200}),
-            "four": builder.buildValue({"XPlacement": 400}),
-            "five": builder.buildValue({"XPlacement": 500}),
-            "six": builder.buildValue({"YPlacement": -6}),
-        }, self.GLYPHMAP)
-        self.assertEqual(sum([getXML(t.toXML) for t in subtables], []),
-                         ['<SinglePos Format="2">',
-                          '  <Coverage>',
-                          '    <Glyph value="one"/>',
-                          '    <Glyph value="two"/>',
-                          '    <Glyph value="three"/>',
-                          '    <Glyph value="four"/>',
-                          '    <Glyph value="five"/>',
-                          '  </Coverage>',
-                          '  <ValueFormat value="1"/>',
-                          '  <!-- ValueCount=5 -->',
-                          '  <Value index="0" XPlacement="500"/>',
-                          '  <Value index="1" XPlacement="500"/>',
-                          '  <Value index="2" XPlacement="200"/>',
-                          '  <Value index="3" XPlacement="400"/>',
-                          '  <Value index="4" XPlacement="500"/>',
-                          '</SinglePos>',
-                          '<SinglePos Format="1">',
-                          '  <Coverage>',
-                          '    <Glyph value="six"/>',
-                          '  </Coverage>',
-                          '  <ValueFormat value="2"/>',
-                          '  <Value YPlacement="-6"/>',
-                          '</SinglePos>'])
+        subtables = builder.buildSinglePos(
+            {
+                "one": builder.buildValue({"XPlacement": 500}),
+                "two": builder.buildValue({"XPlacement": 500}),
+                "three": builder.buildValue({"XPlacement": 200}),
+                "four": builder.buildValue({"XPlacement": 400}),
+                "five": builder.buildValue({"XPlacement": 500}),
+                "six": builder.buildValue({"YPlacement": -6}),
+            },
+            self.GLYPHMAP,
+        )
+        assert sum([getXML(t.toXML) for t in subtables], []) == [
+            '<SinglePos Format="2">',
+            "  <Coverage>",
+            '    <Glyph value="one"/>',
+            '    <Glyph value="two"/>',
+            '    <Glyph value="three"/>',
+            '    <Glyph value="four"/>',
+            '    <Glyph value="five"/>',
+            "  </Coverage>",
+            '  <ValueFormat value="1"/>',
+            "  <!-- ValueCount=5 -->",
+            '  <Value index="0" XPlacement="500"/>',
+            '  <Value index="1" XPlacement="500"/>',
+            '  <Value index="2" XPlacement="200"/>',
+            '  <Value index="3" XPlacement="400"/>',
+            '  <Value index="4" XPlacement="500"/>',
+            "</SinglePos>",
+            '<SinglePos Format="1">',
+            "  <Coverage>",
+            '    <Glyph value="six"/>',
+            "  </Coverage>",
+            '  <ValueFormat value="2"/>',
+            '  <Value YPlacement="-6"/>',
+            "</SinglePos>",
+        ]
 
     def test_buildSinglePos_ValueFormat0(self):
-        subtables = builder.buildSinglePos({
-            "zero": builder.buildValue({})
-        }, self.GLYPHMAP)
-        self.assertEqual(sum([getXML(t.toXML) for t in subtables], []),
-                         ['<SinglePos Format="1">',
-                          '  <Coverage>',
-                          '    <Glyph value="zero"/>',
-                          '  </Coverage>',
-                          '  <ValueFormat value="0"/>',
-                          '</SinglePos>'])
+        subtables = builder.buildSinglePos(
+            {"zero": builder.buildValue({})}, self.GLYPHMAP
+        )
+        assert sum([getXML(t.toXML) for t in subtables], []) == [
+            '<SinglePos Format="1">',
+            "  <Coverage>",
+            '    <Glyph value="zero"/>',
+            "  </Coverage>",
+            '  <ValueFormat value="0"/>',
+            "</SinglePos>",
+        ]
 
     def test_buildSinglePosSubtable_format1(self):
-        subtable = builder.buildSinglePosSubtable({
-            "one": builder.buildValue({"XPlacement": 777}),
-            "two": builder.buildValue({"XPlacement": 777}),
-        }, self.GLYPHMAP)
-        self.assertEqual(getXML(subtable.toXML),
-                         ['<SinglePos Format="1">',
-                          '  <Coverage>',
-                          '    <Glyph value="one"/>',
-                          '    <Glyph value="two"/>',
-                          '  </Coverage>',
-                          '  <ValueFormat value="1"/>',
-                          '  <Value XPlacement="777"/>',
-                          '</SinglePos>'])
+        subtable = builder.buildSinglePosSubtable(
+            {
+                "one": builder.buildValue({"XPlacement": 777}),
+                "two": builder.buildValue({"XPlacement": 777}),
+            },
+            self.GLYPHMAP,
+        )
+        assert getXML(subtable.toXML) == [
+            '<SinglePos Format="1">',
+            "  <Coverage>",
+            '    <Glyph value="one"/>',
+            '    <Glyph value="two"/>',
+            "  </Coverage>",
+            '  <ValueFormat value="1"/>',
+            '  <Value XPlacement="777"/>',
+            "</SinglePos>",
+        ]
 
     def test_buildSinglePosSubtable_format2(self):
-        subtable = builder.buildSinglePosSubtable({
-            "one": builder.buildValue({"XPlacement": 777}),
-            "two": builder.buildValue({"YPlacement": -888}),
-        }, self.GLYPHMAP)
-        self.assertEqual(getXML(subtable.toXML),
-                         ['<SinglePos Format="2">',
-                          '  <Coverage>',
-                          '    <Glyph value="one"/>',
-                          '    <Glyph value="two"/>',
-                          '  </Coverage>',
-                          '  <ValueFormat value="3"/>',
-                          '  <!-- ValueCount=2 -->',
-                          '  <Value index="0" XPlacement="777"/>',
-                          '  <Value index="1" YPlacement="-888"/>',
-                          '</SinglePos>'])
+        subtable = builder.buildSinglePosSubtable(
+            {
+                "one": builder.buildValue({"XPlacement": 777}),
+                "two": builder.buildValue({"YPlacement": -888}),
+            },
+            self.GLYPHMAP,
+        )
+        assert getXML(subtable.toXML) == [
+            '<SinglePos Format="2">',
+            "  <Coverage>",
+            '    <Glyph value="one"/>',
+            '    <Glyph value="two"/>',
+            "  </Coverage>",
+            '  <ValueFormat value="3"/>',
+            "  <!-- ValueCount=2 -->",
+            '  <Value index="0" XPlacement="777"/>',
+            '  <Value index="1" YPlacement="-888"/>',
+            "</SinglePos>",
+        ]
 
     def test_buildValue(self):
         value = builder.buildValue({"XPlacement": 7, "YPlacement": 23})
         func = lambda writer, font: value.toXML(writer, font, valueName="Val")
-        self.assertEqual(getXML(func),
-                         ['<Val XPlacement="7" YPlacement="23"/>'])
+        assert getXML(func) == ['<Val XPlacement="7" YPlacement="23"/>']
 
     def test_getLigatureKey(self):
         components = lambda s: [tuple(word) for word in s.split()]
         c = components("fi fl ff ffi fff")
         c.sort(key=builder._getLigatureKey)
-        self.assertEqual(c, components("fff ffi ff fi fl"))
+        assert c == components("fff ffi ff fi fl")
 
     def test_getSinglePosValueKey(self):
-        device = builder.buildDevice({10:1, 11:3})
+        device = builder.buildDevice({10: 1, 11: 3})
         a1 = builder.buildValue({"XPlacement": 500, "XPlaDevice": device})
         a2 = builder.buildValue({"XPlacement": 500, "XPlaDevice": device})
         b = builder.buildValue({"XPlacement": 500})
         keyA1 = builder._getSinglePosValueKey(a1)
         keyA2 = builder._getSinglePosValueKey(a1)
         keyB = builder._getSinglePosValueKey(b)
-        self.assertEqual(keyA1, keyA2)
-        self.assertEqual(hash(keyA1), hash(keyA2))
-        self.assertNotEqual(keyA1, keyB)
-        self.assertNotEqual(hash(keyA1), hash(keyB))
+        assert keyA1 == keyA2
+        assert hash(keyA1) == hash(keyA2)
+        assert keyA1 != keyB
+        assert hash(keyA1) != hash(keyB)
 
 
-class ClassDefBuilderTest(unittest.TestCase):
+class ClassDefBuilderTest(object):
     def test_build_usingClass0(self):
         b = builder.ClassDefBuilder(useClass0=True)
         b.add({"aa", "bb"})
@@ -1015,14 +1075,8 @@
         b.add({"c"})
         b.add({"e", "f", "g", "h"})
         cdef = b.build()
-        self.assertIsInstance(cdef, otTables.ClassDef)
-        self.assertEqual(cdef.classDefs, {
-            "a": 2,
-            "b": 2,
-            "c": 3,
-            "aa": 1,
-            "bb": 1
-        })
+        assert isinstance(cdef, otTables.ClassDef)
+        assert cdef.classDefs == {"a": 2, "b": 2, "c": 3, "aa": 1, "bb": 1}
 
     def test_build_notUsingClass0(self):
         b = builder.ClassDefBuilder(useClass0=False)
@@ -1030,30 +1084,31 @@
         b.add({"c"})
         b.add({"e", "f", "g", "h"})
         cdef = b.build()
-        self.assertIsInstance(cdef, otTables.ClassDef)
-        self.assertEqual(cdef.classDefs, {
+        assert isinstance(cdef, otTables.ClassDef)
+        assert cdef.classDefs == {
             "a": 2,
             "b": 2,
             "c": 3,
             "e": 1,
             "f": 1,
             "g": 1,
-            "h": 1
-        })
+            "h": 1,
+        }
 
     def test_canAdd(self):
         b = builder.ClassDefBuilder(useClass0=True)
         b.add({"a", "b", "c", "d"})
         b.add({"e", "f"})
-        self.assertTrue(b.canAdd({"a", "b", "c", "d"}))
-        self.assertTrue(b.canAdd({"e", "f"}))
-        self.assertTrue(b.canAdd({"g", "h", "i"}))
-        self.assertFalse(b.canAdd({"b", "c", "d"}))
-        self.assertFalse(b.canAdd({"a", "b", "c", "d", "e", "f"}))
-        self.assertFalse(b.canAdd({"d", "e", "f"}))
-        self.assertFalse(b.canAdd({"f"}))
+        assert b.canAdd({"a", "b", "c", "d"})
+        assert b.canAdd({"e", "f"})
+        assert b.canAdd({"g", "h", "i"})
+        assert not b.canAdd({"b", "c", "d"})
+        assert not b.canAdd({"a", "b", "c", "d", "e", "f"})
+        assert not b.canAdd({"d", "e", "f"})
+        assert not b.canAdd({"f"})
 
 
 if __name__ == "__main__":
     import sys
-    sys.exit(unittest.main())
+
+    sys.exit(pytest.main(sys.argv))
diff --git a/Tests/varLib/data/master_sparse_cff2/MasterSet_Kanji-w0.00.ttx b/Tests/varLib/data/master_sparse_cff2/MasterSet_Kanji-w0.00.ttx
index 5773158..f6568fd 100644
--- a/Tests/varLib/data/master_sparse_cff2/MasterSet_Kanji-w0.00.ttx
+++ b/Tests/varLib/data/master_sparse_cff2/MasterSet_Kanji-w0.00.ttx
@@ -374,6 +374,7 @@
           <FontName value="MasterSet_Kanji-w0.00-Generic"/>
           <Private>
             <BlueValues value="-250 -250 1100 1100"/>
+            <FamilyBlues value="-250 -240 1100 1110"/>
             <BlueScale value="0.039625"/>
             <BlueShift value="7"/>
             <BlueFuzz value="0"/>
diff --git a/Tests/varLib/data/test_results/BuildMain.ttx b/Tests/varLib/data/test_results/BuildMain.ttx
index 7150a57..7e5d956 100644
--- a/Tests/varLib/data/test_results/BuildMain.ttx
+++ b/Tests/varLib/data/test_results/BuildMain.ttx
@@ -55,7 +55,7 @@
          will be recalculated by the compiler -->
     <version value="4"/>
     <xAvgCharWidth value="506"/>
-    <usWeightClass value="400"/>
+    <usWeightClass value="368"/>
     <usWidthClass value="5"/>
     <fsType value="00000000 00000100"/>
     <ySubscriptXSize value="650"/>
diff --git a/Tests/varLib/data/test_results/BuildTestCFF2.ttx b/Tests/varLib/data/test_results/BuildTestCFF2.ttx
index 91b83fc..2904452 100644
--- a/Tests/varLib/data/test_results/BuildTestCFF2.ttx
+++ b/Tests/varLib/data/test_results/BuildTestCFF2.ttx
@@ -86,10 +86,10 @@
             <BlueShift value="7"/>
             <BlueFuzz value="0"/>
             <StdHW>
-                <blend value="67 -39.0 67.0"/>
+                <blend value="67 -39 67"/>
             </StdHW>
             <StdVW>
-                <blend value="85 -51.0 87.0"/>
+                <blend value="85 -51 87"/>
             </StdVW>
           </Private>
         </FontDict>
diff --git a/Tests/varLib/data/test_results/SparseMasters.ttx b/Tests/varLib/data/test_results/SparseMasters.ttx
index 06e58c9..c2aa335 100644
--- a/Tests/varLib/data/test_results/SparseMasters.ttx
+++ b/Tests/varLib/data/test_results/SparseMasters.ttx
@@ -55,7 +55,7 @@
          will be recalculated by the compiler -->
     <version value="4"/>
     <xAvgCharWidth value="580"/>
-    <usWeightClass value="400"/>
+    <usWeightClass value="350"/>
     <usWidthClass value="5"/>
     <fsType value="00000000 00000100"/>
     <ySubscriptXSize value="650"/>
diff --git a/Tests/varLib/data/test_results/TestNonMarkingCFF2.ttx b/Tests/varLib/data/test_results/TestNonMarkingCFF2.ttx
index 5ded5b9..26bd7ba 100644
--- a/Tests/varLib/data/test_results/TestNonMarkingCFF2.ttx
+++ b/Tests/varLib/data/test_results/TestNonMarkingCFF2.ttx
@@ -31,10 +31,10 @@
             <BlueShift value="7"/>
             <BlueFuzz value="0"/>
             <StdHW>
-                <blend value="28 39.0"/>
+                <blend value="28 39"/>
             </StdHW>
             <StdVW>
-                <blend value="34 51.0"/>
+                <blend value="34 51"/>
             </StdVW>
           </Private>
         </FontDict>
diff --git a/Tests/varLib/data/test_results/TestSparseCFF2VF.ttx b/Tests/varLib/data/test_results/TestSparseCFF2VF.ttx
index 442ae91..f05f62f 100644
--- a/Tests/varLib/data/test_results/TestSparseCFF2VF.ttx
+++ b/Tests/varLib/data/test_results/TestSparseCFF2VF.ttx
@@ -132,6 +132,7 @@
         <FontDict index="0">
           <Private>
             <BlueValues value="-250 -250 1100 1100"/>
+            <FamilyBlues value="-250 -240 1100 1110"/>
             <BlueScale value="0.039625"/>
             <BlueShift value="7"/>
             <BlueFuzz value="0"/>
diff --git a/Tests/varLib/varLib_test.py b/Tests/varLib/varLib_test.py
index e29befb..ec05d56 100644
--- a/Tests/varLib/varLib_test.py
+++ b/Tests/varLib/varLib_test.py
@@ -4,6 +4,7 @@
 from fontTools.varLib import build
 from fontTools.varLib.mutator import instantiateVariableFont
 from fontTools.varLib import main as varLib_main, load_masters
+from fontTools.varLib import set_default_weight_width_slant
 from fontTools.designspaceLib import (
     DesignSpaceDocumentError, DesignSpaceDocument, SourceDescriptor,
 )
@@ -661,5 +662,81 @@
     return extracted_kerning
 
 
+@pytest.fixture
+def ttFont():
+    f = TTFont()
+    f["OS/2"] = newTable("OS/2")
+    f["OS/2"].usWeightClass = 400
+    f["OS/2"].usWidthClass = 100
+    f["post"] = newTable("post")
+    f["post"].italicAngle = 0
+    return f
+
+
+class SetDefaultWeightWidthSlantTest(object):
+    @pytest.mark.parametrize(
+        "location, expected",
+        [
+            ({"wght": 0}, 1),
+            ({"wght": 1}, 1),
+            ({"wght": 100}, 100),
+            ({"wght": 1000}, 1000),
+            ({"wght": 1001}, 1000),
+        ],
+    )
+    def test_wght(self, ttFont, location, expected):
+        set_default_weight_width_slant(ttFont, location)
+
+        assert ttFont["OS/2"].usWeightClass == expected
+
+    @pytest.mark.parametrize(
+        "location, expected",
+        [
+            ({"wdth": 0}, 1),
+            ({"wdth": 56}, 1),
+            ({"wdth": 57}, 2),
+            ({"wdth": 62.5}, 2),
+            ({"wdth": 75}, 3),
+            ({"wdth": 87.5}, 4),
+            ({"wdth": 100}, 5),
+            ({"wdth": 112.5}, 6),
+            ({"wdth": 125}, 7),
+            ({"wdth": 150}, 8),
+            ({"wdth": 200}, 9),
+            ({"wdth": 201}, 9),
+            ({"wdth": 1000}, 9),
+        ],
+    )
+    def test_wdth(self, ttFont, location, expected):
+        set_default_weight_width_slant(ttFont, location)
+
+        assert ttFont["OS/2"].usWidthClass == expected
+
+    @pytest.mark.parametrize(
+        "location, expected",
+        [
+            ({"slnt": -91}, -90),
+            ({"slnt": -90}, -90),
+            ({"slnt": 0}, 0),
+            ({"slnt": 11.5}, 11.5),
+            ({"slnt": 90}, 90),
+            ({"slnt": 91}, 90),
+        ],
+    )
+    def test_slnt(self, ttFont, location, expected):
+        set_default_weight_width_slant(ttFont, location)
+
+        assert ttFont["post"].italicAngle == expected
+
+    def test_all(self, ttFont):
+        set_default_weight_width_slant(
+            ttFont, {"wght": 500, "wdth": 150, "slnt": -12.0}
+        )
+
+        assert ttFont["OS/2"].usWeightClass == 500
+        assert ttFont["OS/2"].usWidthClass == 8
+        assert ttFont["post"].italicAngle == -12.0
+
+
 if __name__ == "__main__":
     sys.exit(unittest.main())
diff --git a/setup.cfg b/setup.cfg
index c7b9d0a..a5287c0 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 3.43.1
+current_version = 3.43.2
 commit = True
 tag = False
 tag_name = {new_version}
diff --git a/setup.py b/setup.py
index ea4c92a..eca6a35 100755
--- a/setup.py
+++ b/setup.py
@@ -352,7 +352,7 @@
 
 setup(
 	name="fonttools",
-	version="3.43.1",
+	version="3.43.2",
 	description="Tools to manipulate font files",
 	author="Just van Rossum",
 	author_email="just@letterror.com",