assertHTMLEqual() via pytest - django

I prefer pytest-django to the Django way of testing.
It works fine, except that I don't know how to assertHTMLEqual() via pytest.
How to assert that the HTML snippets are almost equal?

Per the docs here it says:
All of Django’s TestCase Assertions are available in pytest_django.asserts
Taking a quick look at the source code here we can see that it imports everything from SimpleTestCase which assertHTMLEqual is a part of.

Related

pytest.mark.parametrize with django.test.SimpleTestCase

I am using pytest 3.2.2 and Django 1.11.5 on Python 3.6.2 on Windows.
The following code
import django.test
import pytest
class ParametrizeTest:
#pytest.mark.parametrize("param", ["a", "b"])
def test_pytest(self, param):
print(param)
assert False
works as expected:
scratch_test.py::ParametrizeTest::test_pytest[a] FAILED
scratch_test.py::ParametrizeTest::test_pytest[b] FAILED
But as soon as I change it to use Django's SimpleTestCase,
like this:
class ParametrizeTest(django.test.SimpleTestCase):
...
it fails with
TypeError: test_pytest() missing 1 required positional argument: 'param'
Can anybody explain why? And what to do against it?
(I actually even need to use django.test.TestCase and access the database.)
I have the following pytest plugins installed:
plugins: random-0.2, mock-1.6.2, django-3.1.2, cov-2.5.1
but turning any one of them (or all of them) off via -p no:random etc. does not help.
The Django test class is a unittest.TestCase subclass.
Parametrization is unsupported and this is documented under the section pytest features in unittest.TestCase subclasses:
The following pytest features do not work, and probably never will due to different design philosophies:
Fixtures (except for autouse fixtures)
Parametrization
Custom hooks
If you need parametrized tests and pytest runner, your best bet is to abandon the unittest style - this means move the setup/teardown into fixtures (pytest-django plugin has already implemented the hard parts for you), and use module level functions for your tests.
Use #pytest.mark.django_db
Thanks, wim, for that helpful answer. RTFM, once again.
For clarity, here is the formulation that will work (equivalent to a test inheriting from TestCase, not just SimpleTestCase).
Make sure you have pytest-django installed and then do:
import pytest
#pytest.mark.django_db
class ParametrizeTest:
#pytest.mark.parametrize("param", ["a", "b"])
def test_pytest(self, param):
print(param)
assert False
(BTW: Funnily, one reason why I originally decided to use pytest was that
the idea of using plain test functions instead of test methods appealed to me;
I like lightweight approaches.
But now I almost exclusively use test classes and methods anyway,
because I prefer the explicit grouping of tests they provide.)

Django tests: where to put a simple test that a page contains content?

This is an embarrassingly simple question, but working in Django 1.8, what's the best way to write a test that a web page has rendered and has some text in it?
I already have simple tests for my views that check the status code and the template used:
def test_call_view_bnf_section(self):
response = self.client.get('/bnf/0202')
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'bnf_section.html')
Now I'd like to check, for example, that the text 'BNF Section' is present inside an <h1> tag.
How can I do this? And are these view tests the best place to do that, or should I be writing functional tests using Selenium instead?
For this particular test you can add:
self.assertContains(response, '<h1>BNF Section</h1>')
More in Django Documentation: Writing and running tests and SimpleTestCase.assertContains
This is an easy test and no need to get involved with Selenium, at least for this.

How to run a single test or single TestCase with django-nose?

With Django's normal test runner, you can drill down to run tests in a specific app, a specific subclass of TestCase, or a specific test within a specific subclass of TestCase.
E.g.:
./manage.py test myapp.MyTestCase.test_something
However, django-nose doesn't appear to support anything beyond testing a specific app. How do I replicate the last two behaviors?
Nose supports the following syntax (note : between test script name and test class name):
./manage.py test myapp.tests.test_script:MyTestCase.test_method
The correct answer is ./manage.py test myapp/tests/test_script:MyTestCase.test_method.
Using dots in the relative path did not work for me, but slashes did.

UnitTesting in sikuli - configuration from one place

I would like to ask on UnitTesting in sikuli.
Is there any way to make settings from one place for all test ? Also there are any posibility to import one script (for example login to page) to other test ??
I have serious trouble with that. For example I make import file (config.py) with:
def setUp(self):
...some code...
def tearDown(self):
...some code...
It's really strange because I run test -> it's work,...and after that it didn't.
Do you have same experience? Or how you config your test ...
Thank you.
Because of many odds in the Sikuli IDE implementation of UnitTest (e.g. as in this case: import does not work), I recommend, to generally use the Python UnitTest module directly (just a few lines more coding, but total freedom to do what's needed)
see: https://answers.launchpad.net/sikuli/+faq/1804
I think that there are a few questions that are being asked here. I'll see if I can provide some insights for each.
Is there any way to make settings from one place for all test ?
Like with all unit testing the setUp and tearDown are run before and after each and every unit test.
import one script (for example login to page) to other test ??
Yes, you can reuse code. See the following documentation:
http://doc.sikuli.org/globals.html#importing-other-sikuli-scripts-reuse-code-and-images
I run test -> it's work,...and after that it didn't. Do you have same experience?
To paraphrase the documentation, save before you run and only hit the run button in the unit test panel.
http://sikuli.org/wiki/UnitTesting
Hope this helps.

How do I skip a section of code when unittesting in Django?

In my Django application, I have a section of code that uploads a file to Amazon S3, and I would like to skip this section during unittests. Unittests happen to run with DEBUG=False, so I can't test for settings.DEBUG == True to skip this section. Any ideas?
You really don't want to "skip" code in your unit tests -- if you do, you'll never have coverage for those areas. It's far better to provide a mock interface to external systems, so you can insure that the rest of the code behaves as expected. This is especially critical when dealing with external resources that may be unavailable, as S3 can be in case of network issues, service interruptions, or configuration errors.
Alternately, you could just use the Django S3 storage backend in your production environment, while configuring tests for use local file storage instead.
You could -- and yes, this is a hack -- import the module that does the uploading, and replace the upload function in that module with another function, that does nothing. Something like this:
foo.py:
def bar():
return 42
biz.py:
import foo
print foo.bar() # prints 42
foo.bar = lambda: 37
print foo.bar() # prints 37
Again, it's a hack, but if this is the only place where you're going to need such functionality it might work for you.
You don't skip a function for testing.
You provide a mock implementation for something that you don't want to run as if it were production.
First, you design for testing by making the S3 Uploader a separate class that has exactly the API your application needs.
Then you write a mock version of this class with the same API. All it does is record that it was called.
Finally, you make sure your unit test plugs in your mock object instead of the real S3 Uploader.
Your Django application should not have any changes made -- except the change "injected" into it by the unit test.
Your views.py that does the upload
import the_uploader
import mock_uploader
from django.conf import settings
uploadClass = eval( settings.S3_UPLOAD_CLASS_NAME )
uploader= uploadClass( ... )
Now, you provide two settings.py files. The default settings.py has the proper uploader class name.
For testing, you have a test_settings.py which looks like this.
import settings.py
S3_UPLOAD_CLASS_NAME = "mock_uploader.mock_upload_class"
This allows you to actually test everything.