猿问

如何更改我的代码以与此单元测试兼容?

我正在 Exercism 网站上进行一项练习,并且我已经编写了程序,但它没有通过 Exercism 对其进行的一项测试。不过,我不太清楚我需要做什么来修复它。这是我的代码:


import random


ABILITIES = ['strength', 'dexterity', 'constitution',

             'intelligence', 'wisdom', 'charisma']


class Character:

    def __init__(self):

        for ability in ABILITIES:

            setattr(self, ability, roll_ability())

        self.hitpoints = 10 + modifier(self.constitution)



def modifier(constitution):

    return (constitution - 10) // 2



def roll_ability(dice=4, sides=6):

    rolls = []

    for die in range(dice):

        rolls.append(random.randint(1, sides))

    rolls.remove(min(rolls))

    return sum(rolls)

这是测试文件中失败的代码:


def test_random_ability_is_within_range(self):

        score = Character().ability()

        self.assertIs(score >= 3 and score <= 18, True)

这是失败消息:


________________________________ DndCharacterTest.test_random_ability_is_within_range _________________________________


self = <dnd_character_test.DndCharacterTest testMethod=test_random_ability_is_within_range>


    def test_random_ability_is_within_range(self):

>       score = Character().ability()

E       AttributeError: 'Character' object has no attribute 'ability'


dnd_character_test.py:58: AttributeError

我想我需要一个名为“能力”的对象属性?但它有什么作用?我不喜欢必须如此专门地编写程序才能通过单元测试!我想我需要在开始编写代码之前通读单元测试,这样我才能知道该怎么做?


ibeautiful
浏览 116回答 1
1回答

慕莱坞森

阅读了D&D Character 练习描述后,这里根本没有具体说明。您对必须依靠这里的测试来为您提供规范感到不安是对的,这应该在您的作业中更清楚地描述。测试当然期望有一个Character().ability()方法,并验证该方法返回一个 3-18 范围内的整数,包括 3-18。因此,在描述告诉您如何计算能力以及测试正在寻找什么的内容之间阅读,您只需将您的roll_ability()函数移动到您的Character类并重命名它ability():class Character:&nbsp; &nbsp; def __init__(self):&nbsp; &nbsp; &nbsp; &nbsp; for ability in ABILITIES:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setattr(self, ability, self.ability())&nbsp; &nbsp; &nbsp; &nbsp; self.hitpoints = 10 + modifier(self.constitution)&nbsp; &nbsp; def ability(self, dice=4, sides=6):&nbsp; &nbsp; &nbsp; &nbsp; rolls = []&nbsp; &nbsp; &nbsp; &nbsp; for die in range(dice):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rolls.append(random.randint(1, sides))&nbsp; &nbsp; &nbsp; &nbsp; rolls.remove(min(rolls))&nbsp; &nbsp; &nbsp; &nbsp; return sum(rolls)您自己的实现已经产生了 3 到 18 之间的数字(包括 3 个最高骰子的总和),因此应该毫无问题地通过测试。我已经确认上述实现(加上你的modifier()函数)确实通过了给定的单元测试。从设计的角度来看,您在这里使用单独的功能是正确的。ability()不依赖于任何Character状态,也不是字符实例预期执行的功能。与其把它变成一个方法(带有一个无用的self参数),你可以在这里妥协并把它变成一个@staticmethod:class Character:&nbsp; &nbsp; def __init__(self):&nbsp; &nbsp; &nbsp; &nbsp; for ability in ABILITIES:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setattr(self, ability, self.ability())&nbsp; &nbsp; &nbsp; &nbsp; self.hitpoints = 10 + modifier(self.constitution)&nbsp; &nbsp; @staticmethod&nbsp; &nbsp; def ability(dice=4, sides=6):&nbsp; &nbsp; &nbsp; &nbsp; rolls = []&nbsp; &nbsp; &nbsp; &nbsp; for die in range(dice):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rolls.append(random.randint(1, sides))&nbsp; &nbsp; &nbsp; &nbsp; rolls.remove(min(rolls))&nbsp; &nbsp; &nbsp; &nbsp; return sum(rolls)至于ability()函数实现,您可能想在这里查看干净有效地从 4 个骰子中选出前 3 个的heapq.nlargest()函数:from heapq import nlargestclass Character:&nbsp; &nbsp; # ...&nbsp; &nbsp; @staticmethod&nbsp; &nbsp; def ability(dice=4, sides=6):&nbsp; &nbsp; &nbsp; &nbsp; rolls = (random.randint(1, sides) for _ in range(dice))&nbsp; &nbsp; &nbsp; &nbsp; return sum(nlargest(dice - 1, rolls))我只是根据 YAGNIdice将andsides参数放在此处,或者至少将幻数移动到顶部的大写全局名称中。46
随时随地看视频慕课网APP

相关分类

Python
我要回答