Currently I am using some tests like this:
#pytest.mark.django_db(databases=["default"])
def test_list_boards(api_client):
baker.make(Board)
baker.make(Board, name="new")
url = reverse("v1:boards-list")
response = api_client().get(url)
assert response.status_code == 200
assert len(json.loads(response.content)) == 2
edit:
since I'm not using django User, this is my custom User:
class User:
def __init__(self, token, name, user_id, email, is_mega_user, is_authenticated):
self.token = token
self.name = name
self.user_id = user_id
self.email = email
self.is_mega_user = is_mega_user
self.is_authenticated = is_authenticated
But now, I've added new custom authorization and permission classes in my application, so currently my tests are failling because of it.
And I was thiking: What about when I dont have internet connection? I will not be able to test? How can I handle it?
If you don't need to test the authorization and permission classes, then switch them out for similarly-behaving, but offline, mocks.
Assuming you're using DRF (guessing because of the terminology of "authorization and permission class" and the use of api_client) (though settings changing applies to all frameworks of course), you can
(1) do this in your conftest.py's pytest_configure:
def pytest_configure():
from django.conf import settings
settings.REST_FRAMEWORK["DEFAULT_AUTHENTICATION_CLASSES"] = (...)
(2) or using the pytest-django settings fixture:
def test_without_internets(settings):
settings.REST_FRAMEWORK["DEFAULT_AUTHENTICATION_CLASSES"] = (...)
which you can naturally package into your own fixture (that could be autouse for convenience)
(3) or just plain old with override_settings().
Related
I'm using Apache mod_wsgi to serve django. I'v also use Django-cuser middleware that makes user information always available. And i can't really understand how this middleware works. The specific source code:
class CuserMiddleware(object):
#classmethod
def get_user(cls, default=None):
"""
Retrieve user info
"""
return cls.__users.get(threading.current_thread(), default)
#classmethod
def set_user(cls, user):
"""
Store user info
"""
if isinstance(user, str):
user = User.objects.get(username=user)
cls.__users[threading.current_thread()] = user
Why use threading.current_thread() as a key for user? As i underastand Apache does not create different theads for requests.
I am using Django REST Framework in my app. I need authentication but not the default one. I have a model:
class Worker(models.Model):
token = models.CharField(...)
ip = models.GenericIPAddressField(...)
created_date = models.DateTimeField(...)
last_update = models.DateTimeField(...)
Worker sends messages through my API to view WorkerView which inherits from Django REST Framework's APIView. Token is send in request's header:
class WorkerView(APIView):
def post(self, request):
# some not important code
I have an authenticating method:
def authenticate(request):
try:
ip = request.META.get("REMOTE_ADDR", None)
token = request.META.get("HTTP_AUTHORIZATION", None)
...
I thought about two solutions:
Make a mixin class and inherit it in my WorkerView:
class WorkerView(AuthenticationMixin, APIView)
...
Make a class decorator from my authenticate method and use it like this:
#authenticate
class WorkerView(APIView)
But in both cases I need to pass request argument to authenticate method.
How to do that? Or maybe there's a better solution to my problem?
Why don't You create a custom authentication class as defined here?
http://www.django-rest-framework.org/api-guide/authentication/#custom-authentication
I am unit testing my flask app which uses the flask-login extension.
I am setting up all my tests like this using webtest:
class TestCase(unittest.TestCase):
def setUp(self):
app.config['TESTING'] = True
self.client = webtest.TestApp(app)
But when I try to visit urls through self.client.get() which are decorated with #login_required, I get a 401 error with a message that I am not authorized to access the url.
According to the documentation https://flask-login.readthedocs.org/en/latest/#protecting-views
and this discussion,
setting the config value of 'TESTING' to True should disable the login requirements, but that doesn't seem to be working for me.
Any suggestions?
This because Flask-Login caching TESTING or LOGIN_DISABLED on init_app (https://github.com/maxcountryman/flask-login/blob/master/flask_login.py#L164).
So if you create application and then set something in config then you config changes will ignored.
Better way use application factory with separated configs for production and tests, it also decrease probability get errors with not cleaned application state in tests.
The easiest way reinit login_manager:
class TestCase(unittest.TestCase):
def setUp(self):
app.config['TESTING'] = True
app.login_manager.init_app(app)
self.client = webtest.TestApp(app)
from flask login documentation it's said that :
It can be convenient to globally turn off authentication when unit
testing. To enable this, if the application configuration variable
LOGIN_DISABLED is set to True, this decorator will be ignored.
if you are using application factory design pattern add this to your testing config :
LOGIN_DISABLED = True
or you can add it while creating the app like this :
class TestCase(unittest.TestCase):
def setUp(self):
app.config['LOGIN_DISABLED'] = True
self.client = webtest.TestApp(app)
Hope this will help the others who will have the same problem
I'm not sure if this will help, but:
in my old flaskr project file, I had the configurations in my "flaskr.py" file, and they looked like this:
# configuration
DATABASE = 'flaskr.db'
DEBUG = True
SECRET_KEY = 'development key'
USERNAME = 'admin'
PASSWORD = 'default'
So maybe you would have
TESTING = True
?
I'm working with the fixture module for the first time, trying to get a better set of fixture data so I can make our functional tests more complete.
I'm finding the fixture module a bit clunky, and I'm hoping there's a better way to do what I'm doing. This is a Flask/SQLAlchemy app in Python 2.7, and we're using nose as a test runner.
So I have a set of employees. Employees have roles. There are a few pages with rather complex permissions, and I'd like to make sure those are tested.
I created a DataSet that has each type of role (there are about 15 roles in our app):
class EmployeeData(DataSet):
class Meta:
storable = Employee
class engineer:
username = "engineer"
role = ROLE_ENGINEER
class manager:
username = "manager"
role = ROLE_MANAGER
class admin:
username = "admin"
role = ROLE_ADMIN
and what I'd like to do is write a functional test that checks only the right people can access a page. (The actual permissions are way more complicated, I just wanted a toy example to show you.)
Something like this:
def test_only_admin_can_see_this_page():
for employee in Employee.query.all():
login(employee)
with self.app.test_request_context('/'):
response = self.test_client.get(ADMIN_PAGE)
if employee.role == ROLE_ADMIN
eq_(200, response.status_code)
else:
eq_(401, response.status_code)
logout(employee)
Is there a way to generate the fixture data so my devs don't have to remember to add a line to the fixtures every time we add a role? We have the canonical list of all roles as configuration elsewhere in the app, so I have that.
I'm not wedded to any of this or the fixture module, so I'm happy to hear suggestions!
An option would be to use factory_boy to create your test data.
Assuming that you keep and update accordingly a list of roles (that will be used later on) like this one:
roles = [ROLE_ENGINEER, ROLE_ADMIN, ROLE_MANAGER, ...]
Let's create a factory for the Employee table:
import factory
from somewhere.in.the.app import roles
class EmployeeFactory(factory.alchemy.SQLAlchemyModelFactory):
class Meta:
model = Employee
sqlalchemy_session = session
username = factory.Sequence(lambda n: u'User %d' % n)
# Other attributes
...
# Now the role choice
role = factory.fuzzy.FuzzyChoice(roles)
The FuzzyChoice method takes a list of choices and makes a random choice from this list.
Now this will be able to create any amount of Employee objects on demand.
Using the factory:
from factory.location import EmployeeFactory
def test_only_admin_can_see_this_page():
EmployeeFactory.create_batch(size=100)
for employee in session.query(Employee).all():
login(employee)
with self.app.test_request_context('/'):
response = self.test_client.get(ADMIN_PAGE)
if employee.role == ROLE_ADMIN
eq_(200, response.status_code)
else:
eq_(401, response.status_code)
logout(employee)
Breakdown:
EmployeeFactory.create_batch(size=100) Creates 100 Employee objects in the test session.
We can access those objects from the factory session.
More information about using factory_boy with SQLAlchemy: https://factoryboy.readthedocs.io/en/latest/orms.html?highlight=sqlalchemy#sqlalchemy.
Be careful with session management especially: https://factoryboy.readthedocs.io/en/latest/orms.html?highlight=sqlalchemy#managing-sessions
I would like to store some information at the "request scope" when using google app engine (python). What I mean by this is that I would like to initialize some information when a request is first received, and then be able to access it from anywhere for the life of the request (and only from that request).
An example of this would be if I saved the current user's name at request scope after they were authenticated.
How would I go about doing this sort of thing?
Thanks!
A pattern used in app engine itself seems to be threading.local which you can grep for in the SDK code. Making os.environ request local is done like that in runtime/request_environment.py for example.
A rough example:
import threading
class _State(threading.local):
"""State keeps track of request info"""
user = None
_state = _State()
From elsewhere you could authenticate early on in handler code.
from state import _state
if authentication_passed:
_state.user = user
and provide convenience that can be used in other parts of your code
from state import _state
def get_authenticated_user():
user = _state.user
if not user:
raise AuthenticationError()
return user
You need something like this:-
class BaseHandler(webapp2.RequestHandler):
#A function which is useful in order to determine whether user is logged in
def initialize(self, *a, **kw):
#Do the authentication
self.username = username
class MainHandler(BaseHandler):
def get(self):
print self.username
Now if you inherit BaseHandler class all the request will first go through the initialize method of BaseHandler class and since in the BaseHandler class you are setting the username
and MainHandler inherits form BaseHandler you will have the self.username defined and all the request wil go through initialize method.