Re: [GSOC] Shifting to Py.Test and Improving the Test Suite

2014-04-06 Thread Andrew Pashkin
Some Pytest advocacy:
1) Pytest has convenient tests collection options - you can just specify 
folder to run all tests in it. It is also possible to filter tests by 
regex, and select specific ones.

2) PyUnit:

class MyTestCase(TestCase):
def test_something(self):
   expected_content = ...
   response = self.client(...)
   self.assertEqual(expected_content, response.content)   

Pytest:

def test_something(client): 
expected_content = ...
response = self.client(...)
assert expected_content == response.content

Pytest style is cleaner and complies PEP8. Assertions with assert are more 
readable. It is also possible to group tests, by placing them into class, 
without subclassing something.
4) In Pytest it is possible to define setup functions for modules, classes 
and specific tests.
5) Pytest also has fixture mechanism, which allows to use additional 
resources in tests by specifying fixture names as an arguments (like client) 
- it is good alternative to using setUp's and subclassing something.
6) pytest-xdist plugin provides parallel execution of tests.
7) Pytest has features for writing parametrized tests.

So Pytest is kind of cool and it is easy to migrate to it.

On Friday, February 28, 2014 3:42:17 AM UTC+4, Russell Keith-Magee wrote:
>
>
> On Fri, Feb 28, 2014 at 4:17 AM, Gwildor Sok 
> > wrote:
>
>> Personally I'm a big fan of Py.test, simply because it's so simple and 
>> Pythonic to use. Simple functions with simple assert statements. That's 
>> all. For me this significantly lowers the threshold to write tests and 
>> requires less effort, which in the end results in way more tests written in 
>> Py.test than the testsuite Django is currently using.
>>
>
> This is an argument that I've never understood. Why is typing:
>
> class MyTestCase(TestCase):
>
> such a burden? Because once you've typed that, everything else in the 
> class is "just a method". However, you also get the added benefit of test 
> grouping, and if you've got common setup/teardown requirements, the class 
> provides a place to put them.
>
> I know py.test has a lot of fans, but I'm seriously unconvinced by the 
> "it's so easy to write tests" argument.  
>
> For this proposal to be acceptable to core, it's going to need to start 
> with a *comprehensive* analysis of why py.test is a better approach to 
> take. Don't just assume everyone is on board.
>
> Yours,
> Russ Magee %-)
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/f1133fe6-bd1c-4641-857a-e721e26e4e23%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [GSOC] Shifting to Py.Test and Improving the Test Suite

2014-04-06 Thread Chris Wilson

Hi Andrew,

I'm not a Django core contributor but just a user and occasional patcher. 
I submit some comments on this proposal in the hope that they will be 
useful.


On Sun, 6 Apr 2014, Andrew Pashkin wrote:


Some Pytest advocacy:
1) Pytest has convenient tests collection options - you can just specify folder 
to run all tests in it. It is also possible to
filter tests by regex, and select specific ones.


I do use pytest and it has a lot of good points. Running all tests in a 
directory or a specific file is one of them, as is the better test 
selection logic.



class MyTestCase(TestCase):
    def test_something(self):
   expected_content = ...
   response = self.client(...)
       self.assertEqual(expected_content, response.content)  

Pytest:

def test_something(client):
expected_content = ...
response = self.client(...)
assert expected_content == response.content


But this is not one of them, at least not for me. I strongly dislike this 
style of assertions:



Pytest style is cleaner and complies PEP8. Assertions with assert are more 
readable.


* The difference between "self.assertEquals(a, b)" and "assert a == b" is 
minimal for me.


* It hides a LOT of magic in how pytest goes back and evaluates the 
assertion's arguments again if the assertion fails. Sometimes it gets 
different results (if one of the tested methods has side effects) and then 
the assertion message makes no sense, hides the problem, or pytest breaks.


* It makes it much harder to write custom assertions and get meaningful 
display on error.


It is also possible to group tests, by placing them into class without 
subclassing something.


Grouping tests with decorators allows tests to be members of multiple 
suites, it's true. However this is not something that I've ever needed.


And losing the power of inheritance to add methods to my test classes, by 
not putting tests into classes, is enough to kill this style completely 
for me. I write a LOT of my own assertions:


  https://github.com/aptivate/django-harness/tree/master/django_harness


4) In Pytest it is possible to define setup functions for modules, classes and 
specific tests.


I can do this by adding mixins to test classes. Works fine for me, and 
less magical.


5) Pytest also has fixture mechanism, which allows to use additional 
resources in tests by specifying fixture names as an arguments (like 
client) - it is good alternative to using setUp's and subclassing 
something.


We have named fixtures in Django test classes already, so I don't see that 
as much of an advantage. We can't easily add fixtures in mixins at the 
moment. I've not needed that so far.



6) pytest-xdist plugin provides parallel execution of tests.
7) Pytest has features for writing parametrized tests.

So Pytest is kind of cool and it is easy to migrate to it.


I don't think it's necessary or wise to rewrite the test suite to use 
pytest-style assertions. But better integration of Django and Pytest, and 
the ability to write tests with Pytest-style assertions if you like, would 
certainly have my support (fwiw).


Cheers, Chris.
--
Aptivate | http://www.aptivate.org | Phone: +44 1223 967 838
Citylife House, Sturton Street, Cambridge, CB1 2QF, UK

Aptivate is a not-for-profit company registered in England and Wales
with company number 04980791.

--
You received this message because you are subscribed to the Google Groups "Django 
developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/alpine.DEB.2.02.1404061751310.7500%40lap-x201.
For more options, visit https://groups.google.com/d/optout.


Re: [GSOC] Shifting to Py.Test and Improving the Test Suite

2014-04-06 Thread Łukasz Rekucki
On 6 April 2014 17:24, Andrew Pashkin  wrote:
> Some Pytest advocacy:
> 1) Pytest has convenient tests collection options - you can just specify
> folder to run all tests in it. It is also possible to filter tests by regex,
> and select specific ones.

Sounds good, but unittest's test discovery is not that bad and can be
easily improved.

>
> 2) PyUnit:
>
> class MyTestCase(TestCase):
> def test_something(self):
>expected_content = ...
>response = self.client(...)
>self.assertEqual(expected_content, response.content)
>
> Pytest:
>
> def test_something(client):
> expected_content = ...
> response = self.client(...)
> assert expected_content == response.content
>
> Pytest style is cleaner and complies PEP8.

That is very subjective. Also, Python's standards library uses
unittest, so it's hard to argue that Pytest is more in line with
Python standard library recommendation (which what PEP8 is).

> Assertions with assert are more readable.

Again subjective and the magic involved in Pytest's "assertion
introspection" is rather scary. And you still need custom
methods/functions for non-trivial assertions like assertHTMLEquals or
assertQuerysetEquals.

> It is also possible to group tests, by placing them into class, without 
> subclassing something.

True, but Python is not Java, so I never found that to be a problem.

> 4) In Pytest it is possible to define setup functions for modules, classes
> and specific tests.

As in unittest:
https://docs.python.org/2/library/unittest.html#class-and-module-fixtures

> 6) pytest-xdist plugin provides parallel execution of tests.

The hard part when running tests in parallel is usually how to manage
shared resources (like the database - and no creating a new Oracle
instance in every subprocess is a non-starter!). So while having some
support for that is good, it's not something Django's test suite would
get for free.

> 5) Pytest also has fixture mechanism, which allows to use additional
> resources in tests by specifying fixture names as an arguments (like client)
> - it is good alternative to using setUp's and subclassing something.
> 7) Pytest has features for writing parametrized tests.
>

These two features are actually something worth looking at
(parametrized tests would allow cleaning up a lot of template tests),
but I'm guessing that for the core developers to get convinced you'd
have to show that this two will make a real difference (instead of
focusing on the less important stuff mentioned earlier).

Best regards,
Lucas Rekucki

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/CAEZs-EJM6tGxYsihgebYWXgX5uX3OLaJnrFZR3J1LDqxSa2xQg%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: [GSOC] Shifting to Py.Test and Improving the Test Suite

2014-04-06 Thread Andrew Pashkin


...Sometimes it gets different results (if one of the tested methods 
has side effects) and then the assertion message makes no sense, hides 
the problem, or pytest breaks.


* It makes it much harder to write custom assertions and get 
meaningful display on error.
Can you give an examples for cases with messages/breakings and for 
custom assertions?


Regarding magic in Pytest - yeah - there is some =))
But if think deeper, inheritance and self is also magic, and Pytest just 
uses its own magic (dependency injection) that is differs from OO magic =)


Actually it would be interesting to discuss cases where Pytest cant 
handle (or handle with convennience) what PyUnit can and vice versa.



On 06.04.2014 21:02, Chris Wilson wrote:

Hi Andrew,

I'm not a Django core contributor but just a user and occasional 
patcher. I submit some comments on this proposal in the hope that they 
will be useful.


On Sun, 6 Apr 2014, Andrew Pashkin wrote:


Some Pytest advocacy:
1) Pytest has convenient tests collection options - you can just 
specify folder to run all tests in it. It is also possible to

filter tests by regex, and select specific ones.


I do use pytest and it has a lot of good points. Running all tests in 
a directory or a specific file is one of them, as is the better test 
selection logic.



class MyTestCase(TestCase):
def test_something(self):
expected_content = ...
response = self.client(...)
self.assertEqual(expected_content, response.content)

Pytest:

def test_something(client):
expected_content = ...
response = self.client(...)
assert expected_content == response.content


But this is not one of them, at least not for me. I strongly dislike 
this style of assertions:


Pytest style is cleaner and complies PEP8. Assertions with assert are 
more readable.


* The difference between "self.assertEquals(a, b)" and "assert a == b" 
is minimal for me.


* It hides a LOT of magic in how pytest goes back and evaluates the 
assertion's arguments again if the assertion fails. Sometimes it gets 
different results (if one of the tested methods has side effects) and 
then the assertion message makes no sense, hides the problem, or 
pytest breaks.


* It makes it much harder to write custom assertions and get 
meaningful display on error.


It is also possible to group tests, by placing them into class 
without subclassing something.


Grouping tests with decorators allows tests to be members of multiple 
suites, it's true. However this is not something that I've ever needed.


And losing the power of inheritance to add methods to my test classes, 
by not putting tests into classes, is enough to kill this style 
completely for me. I write a LOT of my own assertions:


https://github.com/aptivate/django-harness/tree/master/django_harness

4) In Pytest it is possible to define setup functions for modules, 
classes and specific tests.


I can do this by adding mixins to test classes. Works fine for me, and 
less magical.


5) Pytest also has fixture mechanism, which allows to use additional 
resources in tests by specifying fixture names as an arguments (like 
client) - it is good alternative to using setUp's and subclassing 
something.


We have named fixtures in Django test classes already, so I don't see 
that as much of an advantage. We can't easily add fixtures in mixins 
at the moment. I've not needed that so far.



6) pytest-xdist plugin provides parallel execution of tests.
7) Pytest has features for writing parametrized tests.

So Pytest is kind of cool and it is easy to migrate to it.


I don't think it's necessary or wise to rewrite the test suite to use 
pytest-style assertions. But better integration of Django and Pytest, 
and the ability to write tests with Pytest-style assertions if you 
like, would certainly have my support (fwiw).


Cheers, Chris.


--
С наилучшими пожеланиями, Андрей Пашкин.
м.т - +7 (985) 898 57 59
Skype - waves_in_fluids
e-mail - andrew.pash...@gmx.co.uk

--
You received this message because you are subscribed to the Google Groups "Django 
developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/5341952A.8000201%40gmx.co.uk.
For more options, visit https://groups.google.com/d/optout.


Re: [GSOC] Shifting to Py.Test and Improving the Test Suite

2014-04-06 Thread Chris Wilson

Hi Andrew,

On Sun, 6 Apr 2014, Andrew Pashkin wrote:

* It makes it much harder to write custom assertions and get meaningful 
display on error.


Can you give an examples for cases with messages/breakings and for custom 
assertions?


I don't have an example of breakage to hand, I ripped out the offending 
code in disgust and replaced it with standard assertions that worked. If I 
find another example I'll be sure to let you know before I do the same 
again.


Regarding custom assertions, how would you write assert_not_redirected 
from 
https://github.com/aptivate/django-harness/blob/master/django_harness/fast_dispatch.py

as a PyTest assertion? Consider the following tests:

def not_redirected(response):
return (response.status_code != 302)


class RedirectViewTests(FastDispatchMixin, TestCase):
def test_redirect_view_with_custom_assertion(self):
response = self.fast_dispatch('my-redirecting-view')
self.assert_not_redirected(response)

def test_redirect_view_with_pytest_assertion(self):
response = self.fast_dispatch('my-redirecting-view')
assert not_redirected(response)

assert_not_redirected is from FastDispatchMixin in 
https://github.com/aptivate/django-harness/blob/master/django_harness/fast_dispatch.py, 
not_redirected is a simple assertion I wrote as a demo, since I don't use 
pytest much myself for this reason. Now compare the output (reformatted 
for readability):


 
RedirectViewTests.test_redirect_view_with_custom_assertion 


main/tests/tests.py:71: in test_redirect_view_with_custom_assertion

  self.assert_not_redirected(response)
.ve/src/django-harness/django_harness/fast_dispatch.py:114: in 
assert_not_redirected

  msg_prefix)
E   AssertionError: 302 != 200 : unexpectedly redirected to 
http://www.google.com/


 
RedirectViewTests.test_redirect_view_with_pytest_assertion 


main/tests/tests.py:75: in test_redirect_view_with_pytest_assertion

  assert not_redirected(response)
E   AssertionError: assert 
not_redirected(0x493da10>)


I.e. my assertion outputs:

AssertionError: 302 != 200 : unexpectedly redirected to 
http://www.google.com/


and the simple Python assertion outputs this:


AssertionError: assert
not_redirected()


How would you generate a useful error message, bearing in mind that you 
can't really access response._headers['location'][1] without first having 
checked that the response is a redirect, which isn't the normal case?


Regarding magic in Pytest - yeah - there is some =)) But if think 
deeper, inheritance and self is also magic, and Pytest just uses its own 
magic (dependency injection) that is differs from OO magic =)


OO "magic" is well known and understood by most Python developers. 
Pytest's magic is (a) largely undocumented (afaik) and (b) relies on 
understanding of Python bytecode which is definitely not common knowledge.


Cheers, Chris.
--
Aptivate | http://www.aptivate.org | Phone: +44 1223 967 838
Citylife House, Sturton Street, Cambridge, CB1 2QF, UK

Aptivate is a not-for-profit company registered in England and Wales
with company number 04980791.

--
You received this message because you are subscribed to the Google Groups "Django 
developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/alpine.DEB.2.02.1404061926030.7500%40lap-x201.
For more options, visit https://groups.google.com/d/optout.