Matcher for no result
This commit is contained in:
35
testtools/_deferredmatchers.py
Normal file
35
testtools/_deferredmatchers.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Copyright (c) testtools developers. See LICENSE for details.
|
||||||
|
|
||||||
|
"""Matchers that operate on Deferreds.
|
||||||
|
|
||||||
|
Depends on Twisted.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from testtools.compat import _u
|
||||||
|
from testtools.matchers import Mismatch
|
||||||
|
|
||||||
|
|
||||||
|
class _NoResult(object):
|
||||||
|
"""Matches a Deferred that has not yet fired."""
|
||||||
|
|
||||||
|
def match(self, deferred):
|
||||||
|
"""Match ``deferred`` if it hasn't fired."""
|
||||||
|
result = []
|
||||||
|
|
||||||
|
def callback(x):
|
||||||
|
result.append(x)
|
||||||
|
# XXX: assertNoResult returns `x` here, but then swallows it if
|
||||||
|
# it's a failure. Not 100% sure why that's the case. I guess maybe
|
||||||
|
# to handle the case where you assert that there's no result but
|
||||||
|
# then later make more assertions / callbacks?
|
||||||
|
return x
|
||||||
|
deferred.addBoth(callback)
|
||||||
|
if result:
|
||||||
|
return Mismatch(
|
||||||
|
_u('%r has already fired with %r' % (deferred, result[0])))
|
||||||
|
|
||||||
|
|
||||||
|
# XXX: Maybe just a constant, rather than a function?
|
||||||
|
def no_result():
|
||||||
|
"""Match a Deferred that has not yet fired."""
|
||||||
|
return _NoResult()
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2008-2013 testtools developers. See LICENSE for details.
|
# Copyright (c) 2008-2015 testtools developers. See LICENSE for details.
|
||||||
|
|
||||||
"""Tests for testtools itself."""
|
"""Tests for testtools itself."""
|
||||||
|
|
||||||
@@ -14,6 +14,7 @@ def test_suite():
|
|||||||
test_compat,
|
test_compat,
|
||||||
test_content,
|
test_content,
|
||||||
test_content_type,
|
test_content_type,
|
||||||
|
test_deferredmatchers,
|
||||||
test_deferredruntest,
|
test_deferredruntest,
|
||||||
test_distutilscmd,
|
test_distutilscmd,
|
||||||
test_fixturesupport,
|
test_fixturesupport,
|
||||||
@@ -34,6 +35,7 @@ def test_suite():
|
|||||||
test_compat,
|
test_compat,
|
||||||
test_content,
|
test_content,
|
||||||
test_content_type,
|
test_content_type,
|
||||||
|
test_deferredmatchers,
|
||||||
test_deferredruntest,
|
test_deferredruntest,
|
||||||
test_distutilscmd,
|
test_distutilscmd,
|
||||||
test_fixturesupport,
|
test_fixturesupport,
|
||||||
|
|||||||
110
testtools/tests/test_deferredmatchers.py
Normal file
110
testtools/tests/test_deferredmatchers.py
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
# Copyright (c) testtools developers. See LICENSE for details.
|
||||||
|
|
||||||
|
"""Tests for Deferred matchers."""
|
||||||
|
|
||||||
|
from extras import try_import
|
||||||
|
|
||||||
|
from testtools.compat import _u
|
||||||
|
from testtools._deferredmatchers import (
|
||||||
|
no_result,
|
||||||
|
)
|
||||||
|
from testtools.matchers import (
|
||||||
|
AfterPreprocessing,
|
||||||
|
Equals,
|
||||||
|
Is,
|
||||||
|
MatchesDict,
|
||||||
|
)
|
||||||
|
from testtools.tests.test_spinner import NeedsTwistedTestCase
|
||||||
|
|
||||||
|
|
||||||
|
defer = try_import('twisted.internet.defer')
|
||||||
|
failure = try_import('twisted.python.failure')
|
||||||
|
|
||||||
|
|
||||||
|
def mismatches(description, details=None):
|
||||||
|
"""Match a ``Mismatch`` object."""
|
||||||
|
if details is None:
|
||||||
|
details = Equals({})
|
||||||
|
|
||||||
|
matcher = MatchesDict({
|
||||||
|
'description': description,
|
||||||
|
'details': details,
|
||||||
|
})
|
||||||
|
|
||||||
|
def get_mismatch_info(mismatch):
|
||||||
|
return {
|
||||||
|
'description': mismatch.describe(),
|
||||||
|
'details': mismatch.get_details(),
|
||||||
|
}
|
||||||
|
|
||||||
|
return AfterPreprocessing(get_mismatch_info, matcher)
|
||||||
|
|
||||||
|
|
||||||
|
def make_failure(exc_value):
|
||||||
|
"""Raise ``exc_value`` and return the failure."""
|
||||||
|
try:
|
||||||
|
raise exc_value
|
||||||
|
except:
|
||||||
|
return failure.Failure()
|
||||||
|
|
||||||
|
|
||||||
|
class NoResultTests(NeedsTwistedTestCase):
|
||||||
|
"""
|
||||||
|
Tests for ``no_result``.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def match(self, thing):
|
||||||
|
return no_result().match(thing)
|
||||||
|
|
||||||
|
def test_unfired_matches(self):
|
||||||
|
# A Deferred that hasn't fired matches no_result.
|
||||||
|
self.assertThat(self.match(defer.Deferred()), Is(None))
|
||||||
|
|
||||||
|
def test_successful_does_no_match(self):
|
||||||
|
# A Deferred that's fired successfully does not match no_result.
|
||||||
|
result = None
|
||||||
|
deferred = defer.succeed(result)
|
||||||
|
mismatch = self.match(deferred)
|
||||||
|
self.assertThat(
|
||||||
|
mismatch, mismatches(Equals(_u(
|
||||||
|
'%r has already fired with %r' % (deferred, result)))))
|
||||||
|
|
||||||
|
def test_failed_does_not_match(self):
|
||||||
|
# A Deferred that's failed does not match no_result.
|
||||||
|
fail = make_failure(RuntimeError('arbitrary failure'))
|
||||||
|
deferred = defer.fail(fail)
|
||||||
|
# Suppress unhandled error in Deferred.
|
||||||
|
self.addCleanup(deferred.addErrback, lambda _: None)
|
||||||
|
mismatch = self.match(deferred)
|
||||||
|
self.assertThat(
|
||||||
|
mismatch, mismatches(Equals(_u(
|
||||||
|
'%r has already fired with %r' % (deferred, fail)))))
|
||||||
|
|
||||||
|
def test_success_after_assertion(self):
|
||||||
|
# We can create a Deferred, assert that it hasn't fired, then fire it
|
||||||
|
# and collect the result.
|
||||||
|
deferred = defer.Deferred()
|
||||||
|
self.assertThat(deferred, no_result())
|
||||||
|
results = []
|
||||||
|
deferred.addCallback(results.append)
|
||||||
|
marker = object()
|
||||||
|
deferred.callback(marker)
|
||||||
|
self.assertThat(results, Equals([marker]))
|
||||||
|
|
||||||
|
def test_failure_after_assertion(self):
|
||||||
|
# We can create a Deferred, assert that it hasn't fired, then fire it
|
||||||
|
# with a failure and collect the result.
|
||||||
|
|
||||||
|
# XXX: Ask Jean-Paul about whether this is good behaviour.
|
||||||
|
deferred = defer.Deferred()
|
||||||
|
self.assertThat(deferred, no_result())
|
||||||
|
results = []
|
||||||
|
deferred.addErrback(results.append)
|
||||||
|
fail = make_failure(RuntimeError('arbitrary failure'))
|
||||||
|
deferred.errback(fail)
|
||||||
|
self.assertThat(results, Equals([fail]))
|
||||||
|
|
||||||
|
|
||||||
|
def test_suite():
|
||||||
|
from unittest2 import TestLoader, TestSuite
|
||||||
|
return TestLoader().loadTestsFromName(__name__)
|
||||||
Reference in New Issue
Block a user