Added a test to check that all spells are valid rst.

This commit is contained in:
Mark Wolfman
2021-04-14 13:04:46 -05:00
parent 4aa43d2bec
commit c8577187b0
7 changed files with 133 additions and 111 deletions
+2 -1
View File
@@ -1,4 +1,5 @@
from dungeonsheets.spells.spells import Spell, create_spell
from dungeonsheets.spells.spells import Spell, create_spell, all_spells
from dungeonsheets.spells.spells_a import *
from dungeonsheets.spells.spells_b import *
from dungeonsheets.spells.spells_c import *
+11
View File
@@ -1,3 +1,14 @@
from dungeonsheets import spells
def all_spells():
"""Generate all the valid spell classes so far defined."""
for spell_name, spell in spells.__dict__.items():
# Check if it's (a) a class and (b) a subclass of ``Spell``
if isinstance(spell, type) and issubclass(spell, Spell):
yield spell
def create_spell(**params):
"""Create a new subclass of ``Spell`` with given default parameters.
+6 -6
View File
@@ -734,15 +734,15 @@ class AstralProjection(Spell):
class Augury(Spell):
"""By casting gem-inlaid sticks, rolling dragon bones, laying out ornate cards, or
employing some other divining tool, you receive an omen from an otherworldly
entity about the results of a specific course of action that you plan to take
within the next 30 minutes. The DM chooses from the following possible omens:
"""By casting gem-inlaid sticks, rolling dragon bones, laying out
ornate cards, or employing some other divining tool, you receive
an omen from an otherworldly entity about the results of a
specific course of action that you plan to take within the next 30
minutes. The DM chooses from the following possible omens:
- Weal, for good results
- Woe, for bad results
- Weal and woe, for both good
and bad results
- Weal and woe, for both good and bad results
- Nothing, for results that aren't especially good or bad
The spell doesn't take into account any possible circumstances
+19 -18
View File
@@ -214,20 +214,22 @@ class ChainLightning(Spell):
class ChaosBolt(Spell):
"""You hurl an undulating, warbling mass of chaotic energy at one
creature in range. Make a ranged spell attack against the
target. On a hit, the target takes 2d8 + 1d6 damage. Choose one of
the dSs. The number rolled on that die determines the attacks
target. On a hit, the target takes ``2d8+1d6`` damage. Choose one
of the d8s. The number rolled on that die determines the attacks
damage type, as shown below.
d8 / Damage Type
1 / Acid
2
/ Cold
3 / Fire
4 / Force
5 / Lightning
6 / Poison
7 / Psychic
8 / Thunder
== ===========
d8 Damage Type
== ===========
1 Acid
2 Cold
3 Fire
4 Force
5 Lightning
6 Poison
7 Psychic
8 Thunder
== ===========
If you roll the same number on both d8s, the chaotic energy leaps
from the target to a different creature of your choice within 30
@@ -624,10 +626,8 @@ class CommuneWithNature(Spell):
about any of the following subjects as they relate to the area:
- terrain and bodies of water
- prevalent plants,
minerals, animals, or peoples
- powerful celestials, fey, fiends, elementals,
or undead
- prevalent plants, minerals, animals, or peoples
- powerful celestials, fey, fiends, elementals, or undead
- influence from other planes of existence
- buildings
@@ -1211,8 +1211,9 @@ class ContinualFlame(Spell):
class ControlFlames(Spell):
"""You choose a nonmagical flame that you can see within range and that fits within
a 5-foot cube. You affect it in one of the following ways:
"""You choose a nonmagical flame that you can see within range and
that fits within a 5-foot cube. You affect it in one of the
following ways:
- You instantaneously expand the flame 5 feet in one direction,
provided that wood or other fuel is present in the new location.
+21 -30
View File
@@ -456,7 +456,8 @@ class GuardianOfNature(Spell):
- You gain 10 temporary hit points.
- You make Constitution saving throws with advantage.
- You make Dexterity- and Wisdom-based attack rolls with advantage.
- You make Dexterity- and Wisdom-based attack rolls with
advantage.
- While you are on the ground, the ground within 15 feet of you is
difficult terrain for your enemies.
@@ -489,47 +490,39 @@ class GuardsAndWards(Spell):
Guards and wards creates the following effects within the warded
area.
Corridors: Fog fills all the warded corridors, making them heavily
obscured. In addition, at each intersection or branching passage
offering a choice of direction, there is a 50 percent chance that
a creature other than you will believe it is going in the opposite
direction from the one it chooses.
Doors: All doors in the warded area are magically locked, as if
sealed by an arcane lock spell. In addition, you can cover up to
ten doors with an illusion (equivalent to the illusory object
- **Corridors.** Fog fills all the warded corridors, making them
heavily obscured. In addition, at each intersection or branching
passage offering a choice of direction, there is a 50 percent
chance that a creature other than you will believe it is going
in the opposite direction from the one it chooses.
- **Doors.** All doors in the warded area are magically locked, as
if sealed by an arcane lock spell. In addition, you can cover up
to ten doors with an illusion (equivalent to the illusory object
function of the m inor illusion spell) to make them appear as
plain sections of wall.
Stairs: Webs fill all stairs in the warded area from top to
- **Stairs.** Webs fill all stairs in the warded area from top to
bottom, as the web spell. These strands regrow in 10 minutes if
they are burned or torn away while guards and wards lasts.
Other Spell Effect: You can place your choice of one of the
- **Other Spell Effect.** You can place your choice of one of the
following magical effects within the warded area of the
stronghold.
- Place dancing lights in four corridors. You can designate a
simple program that the lights repeat as long as guards and
wards lasts.
- Place magic mouth in two locations.
- Place stinking cloud in two locations. The vapors appear in the
places you designate; they return within 10 minutes if dispersed
by wind while guards and wards lasts.
- Place stinking cloud in two locations. The vapors appear in
the places you designate; they return within 10 minutes if
dispersed by wind while guards and wards lasts.
- Place a constant gust of wind in one corridor or room.
- Place a suggestion in one location. You select an area of up to
5 feet square, and any creature that enters or passes through
the area receives the suggestion mentally.
- Place a suggestion in one location. You select an area of up
to 5 feet square, and any creature that enters or passes
through the area receives the suggestion mentally.
The whole warded area radiates magic. A dispel magic cast on a
specific effect, if successful, removes only that effect.
You can create a permanently guarded and warded structure by
casting this spell there every day for one year.
specific effect, if successful, removes only that effect. You can
create a permanently guarded and warded structure by casting this
spell there every day for one year.
"""
name = "Guards And Wards"
@@ -622,12 +615,10 @@ class Gust(Spell):
- One Medium or smaller creature that you choose must succeed on a
Strength saving throw or be pushed up to 5 feet away from you.
- You create a small blast of air capable of moving one object
that is neither held nor carried and that weighs no more than 5
pounds. The object is pushed up to 10 feet away from you. It
isn't pushed with enough force to cause damage.
- You create a harmless sensory affect using air, such as causing
leaves to rustle, wind to slam shutters shut, or your clothing
to ripple in a breeze.
+7 -1
View File
@@ -3,7 +3,7 @@ import os
from pathlib import Path
import subprocess
from dungeonsheets import make_sheets, character
from dungeonsheets import make_sheets, character, spells
EG_DIR = os.path.abspath(os.path.join(os.path.split(__file__)[0], '../examples/'))
CHARFILE = os.path.join(EG_DIR, 'rogue1.py')
@@ -136,3 +136,9 @@ 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 = make_sheets.rst_to_latex(spell.__doc__)
self.assertNotIn("DUadmonition", tex,
f"spell {spell} is not valid reStructured text")
+13 -1
View File
@@ -2,11 +2,23 @@
from unittest import TestCase
from dungeonsheets.spells import create_spell, Spell
from dungeonsheets import spells
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)")
# 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")