i don't see under what criteria that test is sensible in terms of integration, if the helper does the assert, you do not need a assert statement if the helper does not do the assert, the python assertion mechanism on its own is unable to provide the meta-data
as such that test is really only able to test a non-integrated solution and i don't consider it to be of value when talking about integration -- Ronny Am 22.03.2018 um 16:35 schrieb Shawn Brown: > Would a return value helper--as you are thinking about it--be able to > handle cases like test_3passing()? > > def test_3passing(): > with pytest.raises(AssertionError) as excinfo: > assert myfunc(41) > assert 'custom report' in str(excinfo.value) > > I've looked around the code base but I'm not sure where best to hack > on things. I've played with changes to > _pytest.assertion.rewrite._saferepr() but this doesn't seem to be the > right place to address this sort of change (newline handling and other > details are handled elsewhere). > > > On Thu, Mar 22, 2018 at 4:12 AM, Ronny Pfannschmidt > <rpfan...@redhat.com <mailto:rpfan...@redhat.com>> wrote: > > that approach is broken in the sense, that it breaks behaviour > expectations, > an return value helper, that triggers an assertion on its own is > simply no longer a return value helper, but a assertion helper > > supporting it like that would result in a really bad api > > instead having assertion helper that returns a "truthy" object > which can be introspected by pytest and/or negated should be more > suitable > > 2018-03-22 3:39 GMT+01:00 Shawn Brown <03sjbr...@gmail.com > <mailto:03sjbr...@gmail.com>>: > > Ah. It's good to see that this has been thought about before. > > My motivation for asking this question was to perform my due > diligence and make sure I wasn't missing something before > moving ahead. My immediate need is handled by using > assert_myfunc() to raise its own error internally--same as > Floris' example. Though, it's not ideal. > > I know my examples have been vague as I've stripped the > specifics of my project to focus the question specifically on > pytest's behavior and I greatly appreciate everyone who is > giving some thought to this. > > As Ronny mentioned, I'm sure it's possible to address this > without user-facing AST manipulation. But I'm not familiar > enough with the code base to see where I can best hack on the > representations. However, I do have a working AST-based > demonstration (below). This uses a fragile monkey-patch that > is just asking for trouble so please take this for the > experimental hack it is... > > > FILE "conftest.py": > > import ast > import _pytest > > def my_ast_prerewrite_hook(ast_assert): > """Modifies AST of certain asserts before > pytest-rewriting.""" > # Demo AST-tree manipulation (actual implemenation > # would need to be more careful than this). > if (isinstance(ast_assert.test, ast.Call) > and isinstance(ast_assert.test.func, ast.Name) > and ast_assert.test.func.id > <http://ast_assert.test.func.id> == 'myfunc'): > > ast_assert.test.func = ast.Name('assert_myfunc', > ast.Load()) > > return ast_assert > > # UNDESIRABLE MONKEY PATCHING!!! > class > ModifiedRewriter(_pytest.assertion.rewrite.AssertionRewriter): > def visit_Assert(self, assert_): > assert_ = my_ast_prerewrite_hook(assert_) # <- > PRE-REWRITE HOOK > return super(ModifiedRewriter, > self).visit_Assert(assert_) > > def rewrite_asserts(mod, module_path=None, config=None): > ModifiedRewriter(module_path, config).run(mod) > > _pytest.assertion.rewrite.rewrite_asserts = rewrite_asserts > > > FILE "test_ast_hook_approach.py": > > import pytest > > # Test helpers. > def myfunc(x): > return x == 42 > > def assert_myfunc(x): > __tracebackhide__ = True > if not myfunc(x): > msg = 'custom report\nmulti-line > output\nmyfunc({0}) failed' > raise AssertionError(msg.format(x)) > return True > > # Test cases. > def test_1passing(): > assert myfunc(42) > > def test_2passing(): > assert myfunc(41) is False > > def test_3passing(): > with pytest.raises(AssertionError) as excinfo: > assert myfunc(41) > assert 'custom report' in str(excinfo.value) > > def test_4failing(): > assert myfunc(41) > > > Running the above test gives 3 passing cases and 1 failing > case (which uses the custom report). Also, test_2passing() > checks for "is False" instead of just "== False" which I think > would be wonderful to support as it removes all caveats for > the user (so users get a real False when they expect False, > instead of a Falsey alternative). Also, if I were going to use > AST manipulation like this, I would probably reference > assert_myfunc() by attaching it as a private attribute to > myfunc() itself -- and then reference it with ast.Attribute() > node instead of an ast.Name(). But again, solving this without > AST manipulation could be better in many ways. > > --Shawn > > > On Mon, Mar 19, 2018 at 1:59 PM, Ronny Pfannschmidt > <i...@ronnypfannschmidt.de <mailto:i...@ronnypfannschmidt.de>> > wrote: > > hi everyone, > > this is just about single value assertion helpers > > i logged an feature request about that a few year back > see https://github.com/pytest-dev/pytest/issues/95 > <https://github.com/pytest-dev/pytest/issues/95> - > > so basically this use-case was known since 2011 ^^ and > doesn't require > ast rewriting lice macros, > just proper engineering of the representation and handling > of single > values in the assertion rewriter. > > -- Ronny >
_______________________________________________ pytest-dev mailing list pytest-dev@python.org https://mail.python.org/mailman/listinfo/pytest-dev