値のコナーセンス

値のコナーセンスはいくつかの値を一緒に変更しなければならないときに生じます。これはプロダクションコードとテストコードの間でよく発生します。たとえば、ブログ記事を表す Article クラスを考えてみましょう。これはインスタンス化されるときにテキストコンテンツが与えられ、最初の 'state' は 'draft' です。

class ArticleState(Enum):
    Draft = 1
    Published = 2


class Article(object):

    def __init__(self, contents):
        self.contents = contents
        self.state = ArticleState.Draft

    def publish(self):
        # do whatever is required to publish the article.
        self.state = ArticleState.Published

今、publish メソッドが正しく機能していることを保証する仮のテストを想像してみます。

article = Article("Test Contents")
assert article.state == ArticleState.Draft
article.publish()
assert article.state == ArticleState.Published

ここで問題になるのは、テストが Article クラスの初期状態に関する知識を要求しているということです。もし Article の初期状態が変更されると、このテストは失敗します(このテストは最初のアサーションがテストの意図とほとんど関係がないためおそらく悪いテストですが、よくあるミスです)。ArticleClassInitialState ラベルを加えて Article クラスとテストが同じラベルを参照するようにすれば、このコードは改善されます。

class ArticleState(Enum):
    Draft = 1
    Published = 2
    InitialState = Draft


class Article(object):

    def __init__(self, contents):
        self.contents = contents
        self.state = ArticleState.InitialState

テストは以下のようになります。

article = Article("Test Contents")
assert article.state == ArticleState.InitialState
article.publish()
assert article.state == ArticleState.Published

万が一 Article クラスに状態マシンを変更する必要が生じたら、ArticleState enum を変更することで対応できます。

class ArticleState(Enum):
    Preproduction = 1
    Draft = 2
    Published = 3
    InitialState = Preproduction

以上が、Article クラスとその初期値の間にある迂回のレベルについての説明でした。