Tornado: Reset database before running all tests - python

I am using Python Tornado web server. When I write test, before all tests, I want to do something (such as prepare some data, reset database ...). How can I achieve this in Python or Tornado web server.
In some languages I can easily do this. Example: in Golang, there is a file named main_test.go.
Thanks

In your test folder, you create __init__.py and initialize everything here.
// __init__.py
reset_database()
run_migration()
seed_data()
Noted that, you should configure your project running test from root folder. For example, if your test inside app/tests/api/sample_api.py, your test should be run from app. In this case, __init__.py will always run before running your sample_api.py. Here is the command line I usually run for running all tests inside project:
python -m unittest discover

If you use unittest.TestCase or tornado.testing.*TestCase (which actually are subclasses of unittest.TestCase), look at the setUp() and tearDown() methods. You can wrap everything you want just like
class MyTests(unittest.TestCase):
def setUp(self):
load_data_to_db()
def test_smth(self):
self.assertIsInstance("setUp and tearDown are useful", str)
def tearDown(self):
cleanup_db()

Related

How do I run the test after completing all the tests? (

There are several tests in the tests folder: test_first.py , test_second.py .
Each test checks the operation of the site by creating and modifying projects. I need that, regardless of how I run the tests tests/test_first.py or tests/ upon completion of all tests, the delete_prj function is executed, which deletes the created project after the tests have run. I'm not asking for the task execution code, the answer to the question is enough
Use a session scoped fixture. Something like this:
import pytest
#pytest.fixture(autouse=True, scope="session")
def do_stuff_after_everything_is_done():
yield
delete_prj()
(untested)

Running pytest tests against multiple backends?

I've built a series of tests (using pytest) for a codebase interacting with the Github API (both making calls to it, and receiving webhooks).
Currently, these tests run against a semi-realistic mock of github: calls to github are intercepted through Sentry's Responses and run through a fake github/git implementation (of the bits I need), which can also be interacted with directly from the tests cases. Any webhook which needs to be triggered uses Werkzeug's test client to call back into the WSGI application used as webhook endpoint.
This works nicely, fast (enough) and is an excellent default, but I'd like the option to run these same tests against github itself, and that's where I'm stumped: I need to switch out the current implementations of the systems under test (direct "library" access to the codebase & mock github) with different ones (API access to "externally" run codebase & actual github), and I'm not quite sure how to proceed.
I attempted to use pytest_generate_tests to switch out the fixture implementations (of the codebase & github) via a plugin but I don't quite know if that would even work, and so far my attempts to load a local file as plugin in pytest via pytest -p <package_name> have not been met with much success.
I'd like to know if I'm heading in the right direction, and in that case if anyone can help with using "local" plugins (not installed via setuptools and not conftest.py-based) in pytest.
Not sure if that has any relevance, but I'm using pytest 3.6.0 running on CPython 3.6, requests 2.18.4, responses 0.9.0 and Werkzeug 0.14.1.
There are several ways to approach this. The one I would go for it by default run your mocked tests and then when a command line flag is present test against both the mock and the real version.
So first the easier part, adding a command line option:
def pytest_addoption(parser):
parser.addoption('--github', action='store_true',
help='Also test against real github')
Now this is available via the pytestconfig fixture as pytestconfig.getoption('github'), often also indirectly available, e.g. via the request fixture as request.config.getoption('github').
Now you need to use this parametrize any test which needs to interact with the github API so that they get run both with the mock and with the real instance. Without knowing your code it sounds like a good point would be the Werkzeug client: make this into a fixture and then it can be parameterized to return both a real client or the test client you mention:
#pytest.fixture
def werkzeug_client(werkzeug_client_type):
if werkzeug_client_type == 'real':
return create_the_real_client()
else:
return create_the_mock_client()
def pytest_generate_tests(metafunc):
if 'werkzeug_client_type' in metafunc.fixturenames:
types = ['mock']
if metafunc.config.getoption('github'):
types.append('real')
metafunc.parametrize('werkzeug_client_type', types)
Now if you write your test as:
def test_foo(werkzeug_client):
assert werkzeug_client.whatever()
You will get one test normally and two tests when invoked with pytest --github.
(Be aware hooks must be in conftest.py files while fixtures can be anywhere. Be extra aware that the pytest_addoption hook should really only be used in the toplevel conftest file to avoid you from confusion about when the hook is used by pytest and when not. So you should put all this code in a toplevel conftest.py file really.)

Execute Django Testcase Suite Manually

Scenario:
Suppose I have some python scripts that do maintenance on the DB, if I use unittest to run tests on those scripts then they will interact with the DB and clobber it. So I'm trying to find a way to use the native Django test suite which simulates the DB without clobbering the real one. From the docs it looks like you can run test scripts using manage.py tests /path/to/someTests.py but only on Django > v1.6 (I'm on Django-Nonrel v1.5.5).
I found How do I run a django TestCase manually / against other database, which talks about running individual test cases and it seems dated--it mentions Django v1.2. However, I'd like to manually kick off the entire suite of tests I've defined. Assume for now that I can't kick off the suite using manage.py test myApp (because that's not what I'm doing). I tried kicking off the tests using unittest.main(). This works with one drawback... it completely clobbers the database. Thank goodness for backups.
someTest.py
import unittest
import myModule
from django.test import TestCase
class venvTest(TestCase): # some test
def test_outside_venv(self):
self.failUnlessRaises(EnvironmentError, myModule.main)
if __name__ == '__main__':
unittest.main() # this fires off all tests, with nasty side effect of
# totally clobbering the DB
How can I run python someTest.py and get it to fire off all the testcases using the Django test runner?
I can't even get this to work:
>>> venvTest.run()
Update
Since it's been mentioned in the comments, I asked a similar but different question here: django testing external script. That question concerns using manage.py test /someTestScript.py. This question concerns firing off test cases or a test suite separately from manage.py.

Running the same tests with different configurations

I have some Python code abstracting the database and the business logic on it. This code is already covered by unit tests but now I need to test this code against different DBs (MySQL, SQLite, etc...)
What is the default pattern for passing the same set of tests with different configurations? My goal is making sure that that abstraction layer works as expected independently of the underlying database. If that could help, I'm using nosetests for running tests but it seems that it lacks the Suite Test concept
Best regards.
I like to use test fixtures for situations in which I have several similar tests. In Python, under Nose, I usually implement this as a common test module imported by other modules. For instance, I might use the following file structure:
db_fixtures.py:
import unittest
class BaseDB(unittest.TestCase):
def testFirstOperation(self):
self.db.query("Foo")
def testSecondOperation(self):
self.db.query("Blah")
database_tests.py:
import db_fixtures
class SQliteTest(db_fixtures.BaseDB):
def setUp(self):
self.db = createSqliteconnection()
class MySQLTest(db_fixtures.BaseDB):
def setUp(self):
self.db = createMySQLconnection()
This will run all tests defined in BaseDB on both MySQL and SQlite. Note that I named db_fixtures.py in such a way that it won't be run by Nose.
Nose supports test suites just import and use unittest.TestSuite. In fact nose will happily run any tesys written using the standard lib's unittest module so tesys do not need to be written in the nose style to be discovered by the nose test runner.
However, I suspect you need morw than test suite support to do the kind of testing you are talking about but more detail about your application is necessary to really address that.
use --attrib plugin, and in the commadn line
1. nosetests -s -a 'sqlite'
2. nosetests -s -a 'mysql'

Write unit tests for restish in Python

I'm writing a RESTful API in Python using the restish framework. I would like to write some unit tests (using the unittest package, for example), that will make different requests to my application and validate the results. The unit tests should be able to run as-is, without needing to start a separate web-server process. How do I set up a mock environment using restish to do this?
Thanks
I test everything using WebTest and NoseTests and I can strongly recommend it. It's fast, flexible and easy to set up. Just pass it your wsgi function and you're good to go.
Since restish is a WSGI framework, you can take advantage of any one of a number of WSGI testing tools:
http://wsgi.org/wsgi/Testing
At least a few of those tools, such as Twill, should be able to test your application without starting a separate web server. (For example, see the "Testing WSGI Apps with Twill" link for more details.)
You might want to ask on the restish forum/list if they have a preferred tool for this type of thing.
Restish has a built in TestApp class that can be used to test restish apps.
Assuming you have a "test" dir in your root restish project callte "restest" created with paster.
import os
import unittest
from paste.fixture import TestApp
class RootTest (unittest.TestCase):
def setUp(self):
self.app = TestApp('config:%s/../development.ini' % os.path.dirname(os.path.abspath(__file__)))
def tearDown(self):
self.app = None
def test_html(self):
res = self.app.get('/')
res.mustcontain('Hello from restest!')
if __name__ == '__main__':
unittest.main()

Categories

Resources