From e5ec51b0e7c3222985d33f82aeeabfc26df1ac42 Mon Sep 17 00:00:00 2001 From: Mark Wolfman Date: Fri, 16 Apr 2021 11:28:05 -0500 Subject: [PATCH] Ran flake8 and black against tests. --- tests/test_character.py | 137 ++++++++++++++++++++++---------------- tests/test_dice.py | 8 +-- tests/test_features.py | 17 +++-- tests/test_latex.py | 82 ++++++++++++----------- tests/test_make_sheets.py | 28 ++++---- tests/test_monsters.py | 2 +- tests/test_multiclass.py | 52 +++++++-------- tests/test_readers.py | 79 ++++++++++++++++------ tests/test_spells.py | 25 ++++--- tests/test_stats.py | 49 ++++++++------ tests/test_weapon.py | 6 +- 11 files changed, 278 insertions(+), 207 deletions(-) diff --git a/tests/test_character.py b/tests/test_character.py index 410a5a1..1dc4440 100755 --- a/tests/test_character.py +++ b/tests/test_character.py @@ -1,27 +1,32 @@ #!/usr/bin/env python from unittest import TestCase -from pathlib import Path import warnings from dungeonsheets import race, monsters, exceptions, spells, infusions -from dungeonsheets.character import Character, Wizard, Druid, read_character_file, _resolve_mechanic +from dungeonsheets.character import ( + Character, + Wizard, + Druid, + _resolve_mechanic, +) from dungeonsheets.weapons import Weapon, Shortsword from dungeonsheets.armor import Armor, LeatherArmor, Shield class TestCharacter(TestCase): """Tests for the generic character base class.""" - + def test_constructor(self): char = Character(name="Inara") - + self.assertIsInstance(char, Character) + def test_hit_dice(self): # Test the getter char = Character() char.level = 2 char.hit_dice_faces = 10 - self.assertEqual(char.hit_dice, '2d10') + self.assertEqual(char.hit_dice, "2d10") def test_max_hp(self): char = Wizard(level=3, constitution=12) @@ -29,37 +34,41 @@ class TestCharacter(TestCase): def test_set_attrs(self): char = Character() - char.set_attrs(name='Inara') - self.assertEqual(char.name, 'Inara') + char.set_attrs(name="Inara") + self.assertEqual(char.name, "Inara") # Check that the weapons get loaded as objects not string - char.set_attrs(weapons=['shortsword']) + char.set_attrs(weapons=["shortsword"]) self.assertEqual(len(char.weapons), 1) self.assertTrue(isinstance(char.weapons[0], Shortsword)) # Check that armor and shield gets set_attrs - char.set_attrs(armor='leather armor', shield='shield') + char.set_attrs(armor="leather armor", shield="shield") self.assertFalse(isinstance(char.armor, str)) self.assertFalse(isinstance(char.shield, str)) # Check that race gets set to an object - char.set_attrs(race='high elf') + char.set_attrs(race="high elf") self.assertIsInstance(char.race, race.HighElf) # Check inspiration works char.set_attrs(inspiration=True) self.assertTrue(char.inspiration) char.set_attrs(inspiration=False) self.assertFalse(char.inspiration) - + def test_homebrew_spells(self): char = Character() + class MySpell(spells.Spell): - name="my spell!" + name = "my spell!" + char.set_attrs(spells=(MySpell,)) self.assertIsInstance(char.spells[0], spells.Spell) self.assertEqual(char.spells[0].name, "my spell!") def test_homebrew_infusions(self): char = Character(classes="artificer") + class MyInfusion(infusions.Infusion): - name="my infusion!" + name = "my infusion!" + # Pass an already created infusion class char.set_attrs(infusions=(MyInfusion,)) self.assertIsInstance(char.infusions[0], infusions.Infusion) @@ -69,54 +78,58 @@ class TestCharacter(TestCase): char.set_attrs(infusions=("spam_infusion",)) self.assertIsInstance(char.infusions[0], infusions.Infusion) self.assertEqual(char.infusions[0].name, "Spam Infusion") - + def test_resolve_mechanic(self): # Test a well defined mechanic NewSpell = _resolve_mechanic("mage_hand", spells, None) self.assertTrue(issubclass(NewSpell, spells.Spell)) + # Test an unknown mechanic def new_spell(**params): return spells.Spell + NewSpell = _resolve_mechanic("hocus_pocus", spells, spells.Spell) self.assertTrue(issubclass(NewSpell, spells.Spell)) + # Test direct resolution of a proper subclass class MySpell(spells.Spell): pass + NewSpell = _resolve_mechanic(MySpell, spells, spells.Spell) - + def test_wield_weapon(self): char = Character() char.strength = 14 char.weapon_proficiencies = [Shortsword] # Add a weapon - char.wield_weapon('shortsword') + char.wield_weapon("shortsword") self.assertEqual(len(char.weapons), 1) sword = char.weapons[0] self.assertTrue(isinstance(sword, Weapon)) self.assertTrue(isinstance(sword, Shortsword)) - self.assertEqual(sword.attack_modifier, 4) # str + prof - self.assertEqual(sword.damage, '1d6+2') # str + self.assertEqual(sword.attack_modifier, 4) # str + prof + self.assertEqual(sword.damage, "1d6+2") # str # Check if dexterity is used if it's higher (Finesse weapon) char.weapons = [] char.dexterity = 16 - char.wield_weapon('shortsword') + char.wield_weapon("shortsword") sword = char.weapons[0] - self.assertEqual(sword.attack_modifier, 5) # dex + prof + self.assertEqual(sword.attack_modifier, 5) # dex + prof # Check if race weapon proficiencies are considered char.weapons = [] char.weapon_proficiencies = [] char.race = race.HighElf() - char.wield_weapon('shortsword') + char.wield_weapon("shortsword") sword = char.weapons[0] self.assertEqual(sword.attack_modifier, 5) - + def test_str(self): char = Wizard(name="Inara") - self.assertEqual(str(char), 'Inara') - self.assertEqual(repr(char), '') - + self.assertEqual(str(char), "Inara") + self.assertEqual(repr(char), "") + def test_is_proficient(self): - char = Character(classes=['Wizard']) + char = Character(classes=["Wizard"]) char.weapon_proficiencies sword = Shortsword() # Check for not-proficient weapon @@ -128,24 +141,32 @@ class TestCharacter(TestCase): char.weapon_proficiencies = tuple() char.race = race.HighElf() self.assertTrue(char.is_proficient(sword)) - + def test_proficiencies_text(self): char = Character() - char._proficiencies_text = ('hello', 'world') - self.assertIn('hello', char.proficiencies_text.lower()) - self.assertIn('world', char.proficiencies_text.lower()) + char._proficiencies_text = ("hello", "world") + self.assertIn("hello", char.proficiencies_text.lower()) + self.assertIn("world", char.proficiencies_text.lower()) # Check for extra proficiencies char._proficiencies_text += ("it's", "me") self.assertIn("it's", char.proficiencies_text.lower()) - self.assertIn('me', char.proficiencies_text.lower()) + self.assertIn("me", char.proficiencies_text.lower()) # Check that race proficienceis are included elf = race.HighElf() char.race = elf - expected = ("hello", "world", "longswords", "shortswords", "shortbows", - "longbows", "it's", "me") + expected = ( + "hello", + "world", + "longswords", + "shortswords", + "shortbows", + "longbows", + "it's", + "me", + ) for e in expected: self.assertIn(e, char.proficiencies_text.lower()) - + def test_proficiency_bonus(self): char = Character() char.level = 1 @@ -168,7 +189,7 @@ class TestCharacter(TestCase): self.assertEqual(char.proficiency_bonus, 6) char.level = 20 self.assertEqual(char.proficiency_bonus, 6) - + def test_spell_slots(self): char = Wizard() # Wizard level 1 @@ -181,10 +202,10 @@ class TestCharacter(TestCase): self.assertEqual(char.spell_slots(spell_level=0), 3) self.assertEqual(char.spell_slots(spell_level=1), 3) self.assertEqual(char.spell_slots(spell_level=2), 0) - + def test_equip_armor(self): char = Character(dexterity=16) - char.wear_armor('leather armor') + char.wear_armor("leather armor") self.assertTrue(isinstance(char.armor, Armor)) # Now make sure the armor class is correct self.assertEqual(char.armor_class, 14) @@ -194,25 +215,25 @@ class TestCharacter(TestCase): # Test equipped armor with max dexterity mod_str char.armor.dexterity_mod_max = 1 self.assertEqual(char.armor_class, 12) - + def test_wield_shield(self): char = Character(dexterity=16) - char.wield_shield('shield') + char.wield_shield("shield") self.assertTrue(isinstance(char.shield, Shield), msg=char.shield) # Now make sure the armor class is correct self.assertEqual(char.armor_class, 15) # Try passing an Armor object directly char.wield_shield(Shield) self.assertEqual(char.armor_class, 15) - + def test_speed(self): # Check that the speed pulls from the character's race - char = Character(race='lightfoot halfling') - self.assertEqual(char.speed, '25') + char = Character(race="lightfoot halfling") + self.assertEqual(char.speed, "25") # Check that a character with no race defaults to 30 feet char = Character() char.race = None - self.assertEqual(char.speed, '30') + self.assertEqual(char.speed, "30") class DruidTestCase(TestCase): @@ -221,44 +242,46 @@ class DruidTestCase(TestCase): be ignored.""" char = Druid() with warnings.catch_warnings(): - warnings.filterwarnings('ignore', message="Druids cannot learn spells") - char.set_attrs(spells=['invisibility'], - spells_prepared=['druidcraft']) + warnings.filterwarnings("ignore", message="Druids cannot learn spells") + char.set_attrs(spells=["invisibility"], spells_prepared=["druidcraft"]) # self.assertEqual(len(char.spells), 1) self.assertEqual(len(char.spells), 2) self.assertIn(spells.Druidcraft(), char.spells) - + def test_wild_shapes(self): char = Druid() # Druid level 2 char.level = 2 # Set reasonable wild shapes - char.wild_shapes = ['Wolf'] + char.wild_shapes = ["Wolf"] self.assertIsInstance(char.wild_shapes[0], monsters.Wolf) # Check what happens if a non-existent wild_shape is added with self.assertRaises(exceptions.MonsterError): - char.wild_shapes = ['Wolf', 'Hyperion Loader'] + char.wild_shapes = ["Wolf", "Hyperion Loader"] # Check what happens if a valid monster class is directly added - char.wild_shapes = [monsters.Wolf(), ] + char.wild_shapes = [ + monsters.Wolf(), + ] self.assertIsInstance(char.wild_shapes[0], monsters.Wolf) # Check that invalid monsters aren't accepted - char.wild_shapes = ['Wolf', 'giant eagle'] + char.wild_shapes = ["Wolf", "giant eagle"] self.assertEqual(len(char.wild_shapes), 1) self.assertIsInstance(char.wild_shapes[0], monsters.Wolf) - + def test_moon_druid_wild_shapes(self): # Moon druid level 2 gets beasts up to CR 1 - char = Druid(level=2, wild_shapes=['Ape'], circle='moon') + char = Druid(level=2, wild_shapes=["Ape"], circle="moon") self.assertEqual(len(char.wild_shapes), 1) self.assertIsInstance(char.wild_shapes[0], monsters.Ape) # Moon druid above level 6 gets beasts up to CR level / 3 - char = Druid(level=9, wild_shapes=['ankylosaurus'], circle='moon') + char = Druid(level=9, wild_shapes=["ankylosaurus"], circle="moon") self.assertEqual(len(char.wild_shapes), 1) self.assertIsInstance(char.wild_shapes[0], monsters.Ankylosaurus) - + def test_can_assume_shape(self): class Beast(monsters.Monster): - description = 'beast' + description = "beast" + new_druid = Druid(level=1) low_druid = Druid(level=2) mid_druid = Druid(level=4) @@ -270,7 +293,7 @@ class DruidTestCase(TestCase): self.assertTrue(low_druid.can_assume_shape(beast)) # Check that challenge rating is checked hard_beast = Beast() - hard_beast.challenge_rating = 1/2 + hard_beast.challenge_rating = 1 / 2 really_hard_beast = Beast() really_hard_beast.challenge_rating = 1 self.assertFalse(low_druid.can_assume_shape(hard_beast)) diff --git a/tests/test_dice.py b/tests/test_dice.py index 4c979a6..fc3c606 100644 --- a/tests/test_dice.py +++ b/tests/test_dice.py @@ -3,16 +3,16 @@ from unittest import TestCase from dungeonsheets.exceptions import DiceError from dungeonsheets import dice -class TestDice(TestCase): +class TestDice(TestCase): def test_read_dice_str(self): - out = dice.read_dice_str('1d6') + out = dice.read_dice_str("1d6") self.assertEqual(out.faces, 6) self.assertEqual(out.num, 1) # Multiple digits - out = dice.read_dice_str('15d10') + out = dice.read_dice_str("15d10") self.assertEqual(out.faces, 10) self.assertEqual(out.num, 15) # Check a bad value with self.assertRaises(DiceError): - dice.read_dice_str('Ed15') + dice.read_dice_str("Ed15") diff --git a/tests/test_features.py b/tests/test_features.py index b895020..0226fdf 100644 --- a/tests/test_features.py +++ b/tests/test_features.py @@ -8,21 +8,26 @@ from dungeonsheets.features import create_feature, Feature, all_features class TestFeatures(TestCase): """Tests for features and feature-related activities.""" + def test_all_features(self): # Make sure only features are returned for ThisFeature in all_features(): - self.assertTrue(isinstance(ThisFeature, type), - f"``all_features`` returned {ThisFeature} (not a class)") - self.assertTrue(issubclass(ThisFeature, Feature), - f"``all_features`` returned {ThisFeature} (not a feature)") + self.assertTrue( + isinstance(ThisFeature, type), + f"``all_features`` returned {ThisFeature} (not a class)", + ) + self.assertTrue( + issubclass(ThisFeature, Feature), + f"``all_features`` returned {ThisFeature} (not a feature)", + ) # Pick a couple of known features to spot-check for all_the_features = list(all_features()) self.assertIn(features.FalseIdentity, all_the_features) self.assertIn(features.DivineSmite, all_the_features) - + def test_create_feature(self): NewFeature = create_feature(name="Hello world") self.assertTrue(issubclass(NewFeature, Feature)) - self.assertEqual(NewFeature.name, 'Hello world') + self.assertEqual(NewFeature.name, "Hello world") feature = NewFeature() print(feature, feature.__class__, type(feature)) diff --git a/tests/test_latex.py b/tests/test_latex.py index 2c5bb47..a7efbaf 100644 --- a/tests/test_latex.py +++ b/tests/test_latex.py @@ -1,53 +1,56 @@ import unittest -from dungeonsheets import make_sheets, character, spells, features, latex +from dungeonsheets import spells, features, latex + class MarkdownTestCase(unittest.TestCase): """Check that conversion of markdown formats to LaTeX code works correctly.""" - + def test_rst_bold(self): - text = latex.rst_to_latex('**hello**') - self.assertEqual(text, '\n\\textbf{hello}\n') - + text = latex.rst_to_latex("**hello**") + self.assertEqual(text, "\n\\textbf{hello}\n") + def test_hit_dice(self): - text = latex.rst_to_latex('1d6+3') - self.assertEqual(text.strip("\n"), '\\texttt{1d6+3}') - + text = latex.rst_to_latex("1d6+3") + self.assertEqual(text.strip("\n"), "\\texttt{1d6+3}") + def test_no_text(self): text = latex.rst_to_latex(None) - self.assertEqual(text, '') - + self.assertEqual(text, "") + def test_verbatim(self): - text = latex.rst_to_latex('``hello, world``') - self.assertIn(r'\texttt{hello, world}', text) + text = latex.rst_to_latex("``hello, world``") + self.assertIn(r"\texttt{hello, world}", text) def test_literal_backslash(self): - text = latex.rst_to_latex(r'\\') - self.assertEqual(r'\textbackslash{}', text.strip("\n")) + text = latex.rst_to_latex(r"\\") + self.assertEqual(r"\textbackslash{}", text.strip("\n")) - @unittest.skip("Headings are all screwed up because it treats them as the document title") + @unittest.skip( + "Headings are all screwed up because it treats them as the document title" + ) def test_headings(self): # Simple heading by itself - text = latex.rst_to_latex('Hello, world\n------------\n\nGoodbye, world') - self.assertEqual('\\section*{Hello, world}\n', text) + text = latex.rst_to_latex("Hello, world\n------------\n\nGoodbye, world") + self.assertEqual("\\section*{Hello, world}\n", text) # Simple heading with leading whitespace - text = latex.rst_to_latex(' Hello, world\n ============\n') - self.assertEqual('\\section*{Hello, world}\n', text) + text = latex.rst_to_latex(" Hello, world\n ============\n") + self.assertEqual("\\section*{Hello, world}\n", text) # Heading with text after it - text = latex.rst_to_latex('Hello, world\n============\n\nThis is some text') - self.assertEqual('\\section*{Hello, world}\n\nThis is some text', text) + text = latex.rst_to_latex("Hello, world\n============\n\nThis is some text") + self.assertEqual("\\section*{Hello, world}\n\nThis is some text", text) # Heading with text before it - text = latex.rst_to_latex('This is a paragraph\n\nHello, world\n============\n') - self.assertEqual('This is a paragraph\n\n\\section*{Hello, world}\n', text) + text = latex.rst_to_latex("This is a paragraph\n\nHello, world\n============\n") + self.assertEqual("This is a paragraph\n\n\\section*{Hello, world}\n", text) # Check that levels of headings are parsed appropriately - text = latex.rst_to_latex('Hello, world\n^^^^^^^^^^^^\n') - self.assertEqual('\\subsubsection*{Hello, world}\n', text) - text = latex.rst_to_latex('Hello, world\n^^^^^^^^^^^^\n', top_heading_level=3) - self.assertEqual('\\subparagraph*{Hello, world}\n', text) + text = latex.rst_to_latex("Hello, world\n^^^^^^^^^^^^\n") + self.assertEqual("\\subsubsection*{Hello, world}\n", text) + text = latex.rst_to_latex("Hello, world\n^^^^^^^^^^^^\n", top_heading_level=3) + self.assertEqual("\\subparagraph*{Hello, world}\n", text) # This is a bad heading missing with all the underline on one line - text = latex.rst_to_latex('Hello, world^^^^^^^^^^^^\n') - self.assertEqual('Hello, world\\^\\^\\^\\^\\^\\^\\^\\^\\^\\^\\^\\^\n', text) + text = latex.rst_to_latex("Hello, world^^^^^^^^^^^^\n") + self.assertEqual("Hello, world\\^\\^\\^\\^\\^\\^\\^\\^\\^\\^\\^\\^\n", text) def test_bullet_list(self): tex = latex.rst_to_latex("\n- Hello\n- World\n\n") @@ -67,14 +70,14 @@ class MarkdownTestCase(unittest.TestCase): """ tex = latex.rst_to_latex(real_list) self.assertIn("\\begin{itemize}", tex) - + def test_multiline_bullet_list(self): md_list = """ - Secondhand (you have heard of the target) - +5 - - Firsthand (you have met + - Firsthand (you have met the target) - +0 - - Familiar (you know the target + - Familiar (you know the target well) - -5 """ @@ -100,16 +103,17 @@ class MarkdownTestCase(unittest.TestCase): self.assertNotIn("endfoot", tex) self.assertNotIn("endhead", tex) self.assertNotIn("endfirsthead", tex) - + def test_rst_all_spells(self): for spell in spells.all_spells(): tex = latex.rst_to_latex(spell.__doc__) - self.assertNotIn("DUadmonition", tex, - f"spell {spell} is not valid reStructured text") - + self.assertNotIn( + "DUadmonition", tex, f"spell {spell} is not valid reStructured text" + ) + def test_rst_all_features(self): for feature in features.all_features(): tex = latex.rst_to_latex(feature.__doc__) - self.assertNotIn("DUadmonition", tex, - f"feature {feature} is not valid reStructured text") - + self.assertNotIn( + "DUadmonition", tex, f"feature {feature} is not valid reStructured text" + ) diff --git a/tests/test_make_sheets.py b/tests/test_make_sheets.py index 4e6b686..e77a912 100644 --- a/tests/test_make_sheets.py +++ b/tests/test_make_sheets.py @@ -1,38 +1,36 @@ import unittest import os from pathlib import Path -import subprocess from dungeonsheets import make_sheets, character -EG_DIR = os.path.abspath(os.path.join(os.path.split(__file__)[0], '../examples/')) -CHARFILE = os.path.join(EG_DIR, 'rogue1.py') +EG_DIR = os.path.abspath(os.path.join(os.path.split(__file__)[0], "../examples/")) +CHARFILE = os.path.join(EG_DIR, "rogue1.py") + class CharacterFileTestCase(unittest.TestCase): example_dir = Path(__file__).parent.parent / "examples" - # def test_(self): - # print(self.example_dir) - # subprocess.run(['makesheets', self.example_dir]) + def test_load_character_file(self): charfile = CHARFILE result = make_sheets.load_character_file(charfile) - self.assertEqual(result['strength'], 10) + self.assertEqual(result["strength"], 10) class PdfOutputTeestCase(unittest.TestCase): - basename = 'clara' - + basename = "clara" + def tearDown(self): - temp_files = [f'{self.basename}.pdf'] + temp_files = [f"{self.basename}.pdf"] for f in temp_files: if os.path.exists(f): os.remove(f) - + def test_file_created(self): # Check that a file is created once the function is run - pdf_name = f'{self.basename}.pdf' + pdf_name = f"{self.basename}.pdf" # self.assertFalse(os.path.exists(pdf_name), f'{pdf_name} already exists.') - char = character.Character(name='Clara') - char.saving_throw_proficiencies = ['strength'] + char = character.Character(name="Clara") + char.saving_throw_proficiencies = ["strength"] make_sheets.create_character_pdf(character=char, basename=self.basename) - self.assertTrue(os.path.exists(pdf_name), f'{pdf_name} not created.') + self.assertTrue(os.path.exists(pdf_name), f"{pdf_name} not created.") diff --git a/tests/test_monsters.py b/tests/test_monsters.py index deb1b3c..ef38395 100644 --- a/tests/test_monsters.py +++ b/tests/test_monsters.py @@ -2,7 +2,7 @@ from unittest import TestCase -from dungeonsheets import monsters, exceptions +from dungeonsheets import monsters class MonsterTestCase(TestCase): diff --git a/tests/test_multiclass.py b/tests/test_multiclass.py index 2bee4a8..441cd6b 100644 --- a/tests/test_multiclass.py +++ b/tests/test_multiclass.py @@ -1,38 +1,39 @@ #!/usr/bin/env python from unittest import TestCase -import warnings -from dungeonsheets import race, monsters, exceptions, spells from dungeonsheets.character import Character -from dungeonsheets.weapons import Weapon, Shortsword -from dungeonsheets.armor import Armor, LeatherArmor, Shield +from dungeonsheets.weapons import Shortsword class TestMulticlass(TestCase): """ Tests for Multiclass character. """ + def test_constructor(self): - char = Character(name='Multiclass', - classes=['wizard', 'fighter'], - levels=[5, 4]) + char = Character( + name="Multiclass", classes=["wizard", "fighter"], levels=[5, 4] + ) + self.assertIsInstance(char, Character) def test_level(self): - char = Character(name='Multiclass', - classes=['wizard', 'fighter'], - levels=[5, 4]) + char = Character( + name="Multiclass", classes=["wizard", "fighter"], levels=[5, 4] + ) self.assertEqual(char.level, 9) def test_spellcasting(self): - char = Character(name='Multiclass', - classes=['wizard', 'fighter'], - levels=[5, 4]) + char = Character( + name="Multiclass", classes=["wizard", "fighter"], levels=[5, 4] + ) self.assertEqual(len(char.spellcasting_classes), 1) - char = Character(name='Multiclass', - classes=['wizard', 'fighter'], - subclasses=[None, 'Eldritch Knight'], - levels=[5, 4]) + char = Character( + name="Multiclass", + classes=["wizard", "fighter"], + subclasses=[None, "Eldritch Knight"], + levels=[5, 4], + ) self.assertEqual(len(char.spellcasting_classes), 2) # equivalent spellcasting level: 6 self.assertEqual(char.spell_slots(spell_level=1), 4) @@ -41,20 +42,15 @@ class TestMulticlass(TestCase): self.assertEqual(char.spell_slots(spell_level=4), 0) def test_proficiencies(self): - char1 = Character(name='Multiclass', - classes=['wizard', 'fighter'], - levels=[5, 4]) - for svt in ('intelligence', 'wisdom'): + char1 = Character( + name="Multiclass", classes=["wizard", "fighter"], levels=[5, 4] + ) + for svt in ("intelligence", "wisdom"): self.assertIn(svt, char1.saving_throw_proficiencies) - char2 = Character(name='Multiclass', - classes=['wizard', 'rogue'], - levels=[5, 4]) - char3 = Character(name='Multiclass', - classes=['rogue', 'wizard'], - levels=[4, 5]) + char2 = Character(name="Multiclass", classes=["wizard", "rogue"], levels=[5, 4]) + char3 = Character(name="Multiclass", classes=["rogue", "wizard"], levels=[4, 5]) sword = Shortsword() self.assertTrue(char1.is_proficient(sword)) # multiclassing into Rogue doesn't give simple weapon proficiency self.assertFalse(char2.is_proficient(sword)) self.assertTrue(char3.is_proficient(sword)) - diff --git a/tests/test_readers.py b/tests/test_readers.py index 6338e25..68fb872 100644 --- a/tests/test_readers.py +++ b/tests/test_readers.py @@ -6,21 +6,22 @@ import types from dungeonsheets.readers import read_character_file EG_DIR = (Path(__file__).parent.parent / "examples").resolve() -CHAR_PYTHON_FILE = EG_DIR / 'rogue1.py' -CHAR_JSON_FILE = EG_DIR / 'barbarian3.json' -SPELLCASTER_JSON_FILE = EG_DIR / 'artificer2.json' +CHAR_PYTHON_FILE = EG_DIR / "rogue1.py" +CHAR_JSON_FILE = EG_DIR / "barbarian3.json" +SPELLCASTER_JSON_FILE = EG_DIR / "artificer2.json" + class PythonReaderTests(unittest.TestCase): def test_load_python_file(self): charfile = CHAR_PYTHON_FILE result = read_character_file(charfile) - self.assertEqual(result['strength'], 10) + self.assertEqual(result["strength"], 10) -class JSONReaderTests(unittest.TestCase): +class JSONReaderTests(unittest.TestCase): def test_load_json_file(self): charfile = CHAR_JSON_FILE - with warnings.catch_warnings(record=True) as w: + with warnings.catch_warnings(record=True): result = read_character_file(charfile) expected_data = dict( name="Ulthar Jenkins", @@ -35,9 +36,22 @@ class JSONReaderTests(unittest.TestCase): constitution=19, intelligence=8, hp_max=32, - skill_proficiencies=["athletics", "survival",], - weapon_proficiencies=["simple weapons", "martial weapons", "battleaxe", "handaxe", "light hammer", "warhammer", "unarmed strike",], - _proficiencies_text=["Brewer's Supplies",], + skill_proficiencies=[ + "athletics", + "survival", + ], + weapon_proficiencies=[ + "simple weapons", + "martial weapons", + "battleaxe", + "handaxe", + "light hammer", + "warhammer", + "unarmed strike", + ], + _proficiencies_text=[ + "Brewer's Supplies", + ], languages="common, dwarvish", cp=26, sp=55, @@ -48,13 +62,17 @@ class JSONReaderTests(unittest.TestCase): magic_items=(), armor="", shield="", - personality_traits="Can easily dismember a body\n\nKnow fight battle tactics", + personality_traits=( + "Can easily dismember a body\n\nKnow fight battle tactics" + ), ideals="Vengence", bonds="friends and adventurers.", flaws="Bloodthirsty and wants to solve every problem by murder", - equipment=("warhammer, handaxe, explorer's pack, javelin (4), backpack, " - "bedroll, mess kit, tinderbox, torch (10), rations (10), " - "waterskin, hempen rope"), + equipment=( + "warhammer, handaxe, explorer's pack, javelin (4), backpack, " + "bedroll, mess kit, tinderbox, torch (10), rations (10), " + "waterskin, hempen rope" + ), attacks_and_spellcasting="", spells_prepared=[], spells=[], @@ -65,19 +83,36 @@ class JSONReaderTests(unittest.TestCase): if isinstance(this_result, types.GeneratorType): this_result = list(this_result) self.assertEqual(this_result, val, key) - + def test_load_json_spells(self): charfile = SPELLCASTER_JSON_FILE - with warnings.catch_warnings(record=True) as w: + with warnings.catch_warnings(record=True): result = read_character_file(charfile) expected_data = dict( - spells_prepared=["cure wounds",], - spells=["spare the dying", "fire bolt", "absorb elements", - "alarm", "catapult", "cure wounds", "detect magic", - "disguise self", "expeditious retreat", "faerie fire", - "false life", "feather fall", "grease", "identify", - "jump", "longstrider", "purify food and drink", - "sanctuary", "snare",], + spells_prepared=[ + "cure wounds", + ], + spells=[ + "spare the dying", + "fire bolt", + "absorb elements", + "alarm", + "catapult", + "cure wounds", + "detect magic", + "disguise self", + "expeditious retreat", + "faerie fire", + "false life", + "feather fall", + "grease", + "identify", + "jump", + "longstrider", + "purify food and drink", + "sanctuary", + "snare", + ], ) for key, val in expected_data.items(): this_result = result[key] diff --git a/tests/test_spells.py b/tests/test_spells.py index af617e6..3ddb1fc 100644 --- a/tests/test_spells.py +++ b/tests/test_spells.py @@ -8,32 +8,37 @@ from dungeonsheets.spells import create_spell, Spell, all_spells class TestSpells(TestCase): """Tests for spells and spell-related activities.""" + def test_all_spells(self): # Make sure only spells are returned for ThisSpell in all_spells(): - self.assertTrue(isinstance(ThisSpell, type), - f"``all_spells`` returned {ThisSpell} (not a class)") - self.assertTrue(issubclass(ThisSpell, Spell), - f"``all_spells`` returned {ThisSpell} (not a spell)") + self.assertTrue( + isinstance(ThisSpell, type), + f"``all_spells`` returned {ThisSpell} (not a class)", + ) + self.assertTrue( + issubclass(ThisSpell, Spell), + f"``all_spells`` returned {ThisSpell} (not a spell)", + ) # Pick a couple of known spells to spot-check for all_the_spells = list(all_spells()) self.assertIn(spells.MagicMissile, all_the_spells) self.assertIn(spells.Thunderwave, all_the_spells) - + def test_create_spell(self): NewSpell = create_spell(name="Hello world") self.assertTrue(issubclass(NewSpell, Spell)) - self.assertEqual(NewSpell.name, 'Hello world') + self.assertEqual(NewSpell.name, "Hello world") spell = NewSpell() print(spell, spell.__class__, type(spell)) - + def test_spell_str(self): spell = Spell() spell.name = "My spell" - self.assertEqual(str(spell), 'My spell') + self.assertEqual(str(spell), "My spell") # Try with a ritual spell.ritual = True - self.assertEqual(str(spell), 'My spell (R)') + self.assertEqual(str(spell), "My spell (R)") # Try with a ritual and a concentration spell.concentration = True - self.assertEqual(str(spell), 'My spell (R, C)') + self.assertEqual(str(spell), "My spell (R, C)") diff --git a/tests/test_stats.py b/tests/test_stats.py index 83ecb51..fa8b9c4 100644 --- a/tests/test_stats.py +++ b/tests/test_stats.py @@ -2,27 +2,29 @@ from unittest import TestCase from dungeonsheets import stats, character -class TestStats(TestCase): +class TestStats(TestCase): def test_mod_str(self): - self.assertEqual(stats.mod_str(-3), '-3') - self.assertEqual(stats.mod_str(0), '+0') - self.assertEqual(stats.mod_str(2), '+2') - + self.assertEqual(stats.mod_str(-3), "-3") + self.assertEqual(stats.mod_str(0), "+0") + self.assertEqual(stats.mod_str(2), "+2") + def test_saving_throw(self): # Try it with an ST proficiency class MyClass(character.Character): - saving_throw_proficiencies = ['strength'] + saving_throw_proficiencies = ["strength"] proficiency_bonus = 2 strength = stats.Ability(14) + my_class = MyClass() self.assertEqual(my_class.strength.saving_throw, 4) - + def test_modifier(self): class MyCharacter(character.Character): - saving_throw_proficiencies = ['strength'] + saving_throw_proficiencies = ["strength"] proficiency_bonus = 2 strength = stats.Ability(14) + my_char = MyCharacter() ranges = [ ((1,), -5), @@ -47,46 +49,49 @@ class TestStats(TestCase): for value in range_: my_char.strength = value stat = my_char.strength - msg = f"Stat {value} doesn't produce modifier {target} ({stat.modifier})" + msg = ( + f"Stat {value} doesn't produce modifier {target} ({stat.modifier})" + ) self.assertEqual(stat.modifier, target, msg) - + def test_setter(self): """Verify that this class works as a data descriptor.""" # Set up a dummy class class MyCharacter(character.Character): stat = stats.Ability() + char = MyCharacter() # Check that the stat works as expected once set char.stat = 15 self.assertEqual(char.stat.value, 15) self.assertEqual(char.stat.modifier, 2) - + def test_skill(self): """Test for a skill, that depends on another ability.""" + class MyClass(character.Character): dexterity = stats.Ability(14) - acrobatics = stats.Skill(ability='dexterity') + acrobatics = stats.Skill(ability="dexterity") skill_proficiencies = [] proficiency_bonus = 2 + my_class = MyClass() self.assertEqual(my_class.acrobatics, 2) # Check for a proficiency - my_class.skill_proficiencies = ['acrobatics'] + my_class.skill_proficiencies = ["acrobatics"] self.assertEqual(my_class.acrobatics, 4) def test_findattr(self): """Check if the function can find attributes.""" - class TestClass(): + + class TestClass: my_attr = 47 YourAttr = 53 + test_class = TestClass() # Direct access - self.assertEqual(stats.findattr(test_class, 'my_attr'), - test_class.my_attr) - self.assertEqual(stats.findattr(test_class, 'YourAttr'), - test_class.YourAttr) + self.assertEqual(stats.findattr(test_class, "my_attr"), test_class.my_attr) + self.assertEqual(stats.findattr(test_class, "YourAttr"), test_class.YourAttr) # Swapping spaces for capitalization - self.assertEqual(stats.findattr(test_class, 'my attr'), - test_class.my_attr) - self.assertEqual(stats.findattr(test_class, 'your attr'), - test_class.YourAttr) + self.assertEqual(stats.findattr(test_class, "my attr"), test_class.my_attr) + self.assertEqual(stats.findattr(test_class, "your attr"), test_class.YourAttr) diff --git a/tests/test_weapon.py b/tests/test_weapon.py index 4aad746..65723a2 100644 --- a/tests/test_weapon.py +++ b/tests/test_weapon.py @@ -6,8 +6,8 @@ from dungeonsheets.weapons import Weapon class WeaponTestCase(unittest.TestCase): def test_weapon_damage(self): weapon = Weapon() - weapon.base_damage = '1d6' - self.assertEqual(weapon.damage, '1d6') + weapon.base_damage = "1d6" + self.assertEqual(weapon.damage, "1d6") # Now add some bonus damage weapon.damage_bonus = 2 - self.assertEqual(weapon.damage, '1d6+2') + self.assertEqual(weapon.damage, "1d6+2")