I use bottle & gevent for my python (2.7.6) application.
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from gevent import spawn, monkey
from bottle import Bottle
from .settings import MONGODB_HOST, MONGODB_PORT, MONGODB_NAME
monkey.patch_all()
mongo_client = MongoClient(MONGODB_HOST, MONGODB_PORT)
db = mongo_client[MONGODB_NAME]
class MyApp(object):
def insert_event(self):
data = {'a': self.a, 'b': self.b} # some data
db.events.insert(data)
def request(self):
# request data processing...
spawn(self.insert_event)
return {}
app = Bottle()
app.route('/', method='POST')(MyApp().request)
And I want to test it with mongomock (https://github.com/vmalloc/mongomock).
from __future__ import unicode_literals
from unittest import TestCase
from webtest import TestApp
from mock import patch
from mongomock import MongoClient
from ..app import app as my_app
db = MongoClient().db
#patch('my_app.app.db', db)
class TestViews(TestCase):
def setUp(self):
self.app = TestApp(ssp_app)
self.db = db
def test_request(self):
response = self.app.post('/', {})
last_event = self.db.events.find_one({})
self.assertTrue(last_event)
My test fails.
FAIL: test_request (my_app.tests.TestViews)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/mock/mock.py", line 1305, in patched
return func(*args, **keywargs)
File "/srv/mysite/my_app/tests/views.py", line 71, in test_request
self.assertTrue(last_event)
AssertionError: None is not true
It is work if I use self.insert_event without spawn. I tried to use patch.object, "with" statement, but without success...
I found solution. I need to mock gevent.spawn method. Because I get HTTP response before the coroutine ends. This my solution:
#patch('my_app.app.db', db)
#patch('my_app.app.spawn',
lambda method, *args, **kwargs: method(*args, **kwargs))
class TestViews(TestCase):
Related
I tried to crate simple Python project with flask and unittest. Structure is quite simple:
classes
|-sysinfo
|static
|templates
|- index.html
|- layout.html
|__init__.py
|sysinfo.py
|printinfo.py
tests
|test_sysinfo.py
README.md
requirments.txt
Very simple class in printinfo.py:
#!/usr/bin/python
import psutil
import json
class SysInfo:
.......
def displayInfo(self):
.......
return json.dumps(self.__data)
And simple flask server run with sysinfo.py:
from flask import Flask, flash, redirect, render_template, request, session, abort
from printinfo import SysInfo
import json
obj1 = SysInfo("gb")
app = Flask(__name__)
#app.route('/')
def index():
var = json.loads(obj1.displayInfo())
return render_template('index.html',**locals())
#app.route('/healthcheck')
def healthcheck():
return "Ok"
#app.route("/api/all")
def all():
return obj1.displayInfo()
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)
del obj1
I run it with python sysinfo.py staying in classes/sysinfo folder and everything works ok.
So I decided to run unittest for my application. Put in classes/tests ( also tried classes/sysinfo/tests) file test_sysinfo.py with code:
import unittest
import printinfo
from sysinfo import sysinfo
import json
import sys
class TestFlaskApi(unittest.TestCase):
def setUp(self):
self.app = sysinfo.app.test_client()
def simple_test(self):
response = self.app.get('/health')
self.assertEqual(
json.loads(response.get_data().decode(sys.getdefaultencoding())),
{'healthcheck': 'ok'}
)
if __name__ == "__main__":
unittest.main()
And when I started it I can see error:
Error Traceback (most recent call last):
File "\Python\Python37-32\lib\unittest\case.py", line 59, in testPartExecutor
yield File "\Python\Python37-32\lib\unittest\case.py", line 615, in run
testMethod() File "\Python\Python37-32\lib\unittest\loader.py", line 34, in testFailure
raise self._exception ImportError: Failed to import test module: test_sysinfo Traceback (most recent call last): File
"\Python\Python37-32\lib\unittest\loader.py", line 154, in
loadTestsFromName
module = __import__(module_name) File "\classes\sysinfo\tests\test_sysinfo.py", line 2, in <module>
import printinfo ModuleNotFoundError: No module named 'printinfo'
I read several articles, some topics here on StackOverflow for my understanding it's related to project structure. I tried to create setup.py and setup.cfg. I managed to start it with this setup, but test still didn't work.
Could you please help me with minimum setup applicable for my case? All the material I found had written for specific case or too general. I cannot apply it for my case.
Follow flask tutorial I edit __init__.py file to start app from here:
from flask import Flask, flash, redirect, render_template, request, session, abort
from . import printinfo
import json
import os
obj1 = printinfo.SysInfo("gb")
def create_app(test_config=None):
# create and configure the app
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev'
)
obj1 = printinfo.SysInfo("gb")
#app.route('/')
def index():
var = json.loads(obj1.displayInfo())
return render_template('index.html', **locals())
#app.route('/healthcheck')
def healthcheck():
return "Ok"
#app.route("/api/all")
def all():
return obj1.displayInfo()
#del obj1
return app
Also environment variables should be set for Flask:
For Linux and Mac:
export FLASK_APP=sysinfo
export FLASK_ENV=development
For Windows cmd, use set instead of export:
set FLASK_APP=sysinfo
set FLASK_ENV=development
And run application:
flask run
It run application on localhost on port 5000 since development env set. Anyway I needed to add from . import printinfo into __init__.py.
Didn't try test, but think it should work. If interesting will update soon.
Just followed Flask tutorial. Created conftest.py and test_factory.py. Run Ok with pytest:
import pytest
from sysinfo import create_app
from sysinfo import printinfo
#pytest.fixture
def app():
app = create_app({
'TESTING': True
})
with app.app_context():
printinfo.SysInfo("gb")
yield app
Probably the same setup could be used with unittest. Didn't try.
I have a very primitive Flask application which works as I'm expecting, but I'm failing to write a unit test for it. The code of the app is following (i omit insignificant part):
app.py
from flask import *
import random
import string
app = Flask(__name__)
keys = []
app.testing = True
#app.route('/keygen/api/keys', methods=['POST'])
def create():
symbol = string.ascii_letters + string.digits
key = ''.join(random.choice(symbol) for _ in range(4))
key_instance = {'key': key, 'is_used': False}
keys.append(key_instance)
return jsonify({'keys': keys}), 201
The test is:
tests.py
import unittest
from flask import *
import app
class TestCase(unittest.TestCase):
def test_number_one(self):
test_app = Flask(app)
with test_app.test_client() as client:
rv = client.post('/keygen/api/keys')
...something...
if __name__ == '__main__':
unittest.main()
The traceback:
ERROR: test_number_one (__main__.TestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests.py", line 12, in test_number_one
test_app = Flask(app)
File "/Users/bulrathi/Yandex.Disk.localized/Virtualenvs/ailove/lib/python3.5/site-packages/flask/app.py", line 346, in __init__
root_path=root_path)
File "/Users/bulrathi/Yandex.Disk.localized/Virtualenvs/ailove/lib/python3.5/site-packages/flask/helpers.py", line 807, in __init__
root_path = get_root_path(self.import_name)
File "/Users/bulrathi/Yandex.Disk.localized/Virtualenvs/ailove/lib/python3.5/site-packages/flask/helpers.py", line 668, in get_root_path
filepath = loader.get_filename(import_name)
File "<frozen importlib._bootstrap_external>", line 384, in _check_name_wrapper
ImportError: loader for app cannot handle <module 'app' from '/Users/bulrathi/Yandex.Disk.localized/Обучение/Code/Django practice/ailove/keygen/app.py'>
----------------------------------------------------------------------
Ran 1 test in 0.003s
FAILED (errors=1)
Thanks for your time.
You have a few issues with the posted code (indentation aside):
First, in tests.py you import app and use it, but app is the module rather than the app object from app.py. You should import the actual app object using
from app import app
and secondly, you are using that app object (assuming we fix the import) as a parameter to another Flask() constructor—essentially saying:
app = Flask(Flask(app))
Since we've imported app from app.py, we can just use it directly, so we remove the app = Flask(app) line (and the associated import statement as we don't need it anymore) and your test file becomes:
import unittest
from app import app
class TestCase(unittest.TestCase):
def test_number_one(self):
with app.test_client() as client:
rv = client.post('/keygen/api/keys')
...something...
if __name__ == '__main__':
unittest.main()
You should note also that the from flask import * form is discouraged in favour of importing specific parts of the module, so
from flask import Flask, jsonify
would be better in your app.py.
The tornado testing subject doc is so simple, I am not quite sure how to do a unit test on tornado. like that:
here is a api.py:
import tornado
import logging
from tornado.web import RequestHandler
import time
class AnalyticsBWSpecificHour(RequestHandler):
def get(self):
return self.write({'message':'no get method'})
class Application(tornado.web.Application):
def __init__(self,**kwargs):
api_handlers = [
(r"/", AnalyticsBWSpecificHour),
]
logging.debug(api_handlers)
super(Application, self).__init__(api_handlers, **kwargs)
and the test_tornado.py :
from api import Application
from tornado.testing import AsyncHTTPTestCase
import tornado
import logging
logging.basicConfig(level=logging.DEBUG)
import unittest
class ApiTestCase(AsyncHTTPTestCase):
def get_app(self):
self.app = Application(debug=True)
return self.app
def test_status(self):
print(self.get_url('/'))
response = self.fetch(self.get_url('/'),method='GET')
self.assertEqual(response.code,200)
if __name__ == '__main__':
unittest.main()
even this is quite simple example, I also get the 599 error. please help me.
response = self.fetch(self.get_url('/'),method='GET')
self.fetch() calls self.get_url for you. Either do self.fetch('/') or self.http_client.fetch(self.get_url('/')), but don't mix the two.
Also don't pass debug=True in tests; the autoreload will do the wrong thing in a unittest environment.
I'm trying to set some tests for my server.
According to a friend's recommendation I wanna use unittest and mock. For this purpose I wrote some lines but when I try to execute the script I got an importError.
Traceback (most recent call last):
File "test_creds.py", line 146, in <module>
unittest.main()
AttributeError: 'module' object has no attribute 'main'
Do I have some mistake with the imports?
Thanks!
# coding=utf-8
import sys, os
import unittest, mock, kiss
from twisted.python import log
from twisted.trial import unittest
from twisted.cred import credentials
class CredentialsChecker(unittest.TestCase):
"""
Testing the server credentials handling
"""
def _setUp_databases(self):
username_1 = 'user_name'
password_1 = 'user_pass'
email_1 = 'user#mail.org'
create_user_profile = mock.Mock()
self.db = mock.Mock()
self.db.username = username_1
self.db.password = password_1
self.db.email = email_1
def setUp(self):
log.startLogging(sys.stdout)
log.msg(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Flushing database")
#management.execute_from_command_line(['manage.py', 'flush',\
#'--noinput'])
log.msg(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Populating database")
#management.execute_from_command_line(['manage.py', 'createsuperuser',\
#'--username', 'superuser_name', '--email', 'superuser_name#email.org',\
#'--noinput'])
self._setUp_databases()
log.msg(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Running tests")
return
"""
Log in with valid credentianls. The server should return True
"""
def test_GoodCredentials(self):
creds = credentials.UsernamePassword('user_name', 'user_pass')
checker = DjangoAuthChecker()
d = checker.requestAvatarId(creds)
if __name__ == '__main__':
unittest.main()
If you create an object inheriting from the class unittest.TestCase test you have to use the native Python unittest module.
Please tell me how to solve a following problem.I would like to use webtest with multiprocess but it fails.
It means that I would like to use parallel tests with db.I'm not paticular about multiprocess.
Probably,because of using other process,It can not call db.
result
======================================================================
FAIL: test_answer (testlab.LabTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Library/Python/2.7/site-packages/mock.py", line 1201, in patched
return func(*args, **keywargs)
File "/Users/unko/dropbox/test/testlab.py", line 48, in test_answer
self.assertEqual(u.param,"bar")
AssertionError: 'foo' != 'bar'
----------------------------------------------------------------------
testlab.py
#!-*- coding: utf-8 -*-
import unittest
import webtest
import webapp2
from google.appengine.ext import testbed,ndb
import json
import time
from google.appengine.api import apiproxy_stub_map
from google.appengine.api import urlfetch_stub
from mock import patch, Mock
from google.appengine.ext import db
from lab import Lab
from lab import Unko
import multiprocessing
class LabTestCase(unittest.TestCase):
def setUp(self):
app = webapp2.WSGIApplication([
('/lab', Lab),
('/(.*)', Lab)
],debug=True)
self.testapp = webtest.TestApp(app)
self.testbed = testbed.Testbed()
self.testbed.setup_env(app_id='sagifugoh')
self.testbed.activate()
self.testbed.init_datastore_v3_stub()
self.testbed.init_memcache_stub()
self.testbed.init_channel_stub()
self.testbed.init_urlfetch_stub()
def tearDown(self):
self.testbed.deactivate()
#patch('google.appengine.api.urlfetch.urlfetch_service_pb.URLFetchResponse')
def test_answer(self, URLFetchResponse):
def request(param):
response = self.testapp.post('/lab',{"key":"key","param":param})
def async(param):
p = multiprocessing.Process(target=request,args=[param])
jobs.append(p)
p.start()
jobs = []
u = Unko.get_or_insert("key")
u.param = "foo"
u.put()
async("bar")
time.sleep(2)
self.assertEqual(u.param,"bar")
if __name__ == '__main__':
unittest.main()
lab.py
#!-*- coding: utf-8 -*-
import webapp2
from google.appengine.ext import db
class Unko(db.Model):
param = db.StringProperty()
class Lab(webapp2.RequestHandler):
def post(self):
key = self.request.get('key')
param = self.request.get('param')
u = Unko.get_or_insert(key)
u.param = param
u.put()