Django 2.0 - Make test worker to run tests in non-app folder - django

In Django 2.0, I have following project structure, which I can't change, no matter what:
grocery_store_website
manage.py
grocery_store # contains wsgi, settings,etc.
app1
app1
non-app-utils
__init__.py
helpers.py
serializers.py
model_mixins.py
tests
test_helpers.py # I want test runner to run these.
It turned out, I need to write unit tests for non-app-utils. Mentioned directory is not a registered Django App and never will be. These tests must be located in tests directory, located in non-app-utils. How can I make Django's test runner to discover and run also tests from non-app-utils directory?
If I run Django tests with directly specified path ./manage.py test utils.tests.test_helpers, it works. However ./manage.py test does not. Any ideas how to go on?

Jerin Peter George suggested adding __init__.py file into non-app-utils directory. However, problem was, there is __init__.py file missing in non-app-utils/tests directory!
After I add those and run ./manage.py test, Django's test runner found my tests and ran them as I needed to!

Related

ModuleNotFoundError: No module named 'project.appname' when running Django tests

When trying to run my tests using either ./manage.py test or pytest, all of the apps in my Django project fail their tests with ModuleNotFoundError: No module named 'project.appname'. However, when running with ./manage.py test app.tests (if the tests are in a dedicated tests directory), they do progress beyond a Module Not Found error.
I think there is something wrong with my configuration that leads to this error but I have no idea where to poke to try fixing this: I'm not seeing anything that makes PyCharm yell at me when I look at any testing module nor when looking at Settings.py
Remove the __init__.py file from the project.
e.g.
project/
- appname
...
...
__init__.py # Remove this one.

Django test not running specific app tests

I have an app named "sites" that runs normally through the built in server and I can interact with it without any issues.
I added tests in the standard tests.py file and ran "manage.py test sites"
I have two tests in my tests.py file all starting with "test".
When I run the manage.py command in verbose mode, I get:
test_get_current_site (django-contrib.sites.tests.SitesFrameworkTests) ... ok
test_save_another (django-contrib.sites.tests.SitesFrameworkTests) ... ok
etc.
It looks to me that I have a name conflict with an internal module.
Is there any way I can get manage.py to test my code or should I just bite the bullet and change my app name?
Rename your app. From the docs on the INSTALLED_APPS setting:
App names must be unique
The application names (that is, the final dotted part of the path to the module containing models.py) defined in INSTALLED_APPS must be unique. For example, you can’t include both django.contrib.auth and myproject.auth in INSTALLED_APPS.
In this case, your sites app clashes with the Django sites framework, django.contrib.sites.

How to test single application (not project) in Django?

I would like to test my small application, that I keep in a separate package. Right now I created a "test_project" directory, created a test project there and I am using the project's manage.py to run tests. But I keep wondering - is there a better method? Is it possible to launch a single app's tests, perhaps with some default configuration (like, sqlite database)?
It is possible to run a single app's tests standalone, without creating a Django test project for that purpose. One way of doing so is by creating a runtests.py in your app's root dir which setups Django settings and runs ./manage.py test your_app programmatically. One example of runtests.py is Django's own: runtests.py (documentation).
Django's own runtests.py is a good reference but I find it convoluted for most cases. Below are a couple of alternative examples:
Django-Modeltranslation
My own minimalistic one
Writing this down because I don't see it on here yet
From the docs
If your django structure looks something like this as it should:
Project dir/
/myapp
/myotherapp
/myproject
Django allows you to execute test from only "myotherapp" by executing:
./manage.py test myotherapp/
This will execute all test under "myotherapp" whereas
./manage.py test
will execute all test in your projects directory.
If you use nose you can run a single app's tests.
python manage.py test app.tests:TestClassHere
as for testing a single app. I just follow the convention other big django projects do, and that is exactly what you are doing. Create a test_project directory.
https://github.com/mozilla/django-piston/tree/master/tests/test_project
I figure if it is good enough for some of the biggest django pluggable apps it's good enough for me.
Ofcourse you can test the Python parts with a standalone unittest if you don't need any django dependencies
A Django environment requires atleast a settings.py and manage.py file. You can setup those with essential stuff only and UnitTest your app with manage.py. You should see a project as a Django runtime environment, there's no Django without it. You can probably mimic settings but tbh you would just be creating more hacks than simplicity.
You can also create a custom test runner and override the path it searches for tests in.
Perhaps I buried the lede here. I recently inherited a project that had legacy tests they wanted to keep for historical reasons, so I was forced to write all my tests in one folder and point to it
from django.test.runner import DiscoverRunner
class MyTestRunner(DiscoverRunner):
def __init__(self, *args, **kwargs):
kwargs.update({'top_level': str(settings.TEST_DISCOVER_TOP_LEVEL)})
super().__init__(*args, **kwargs)
def run_tests(self, test_labels, extra_tests=None, **kwargs):
# In order to override the top_level directory, the test_label must match the top_level
kwargs.update({'test_labels': [str(settings.TEST_DISCOVER_TOP_LEVEL)]})
return super().run_tests(extra_tests=extra_tests, **kwargs)
and in your settings
TEST_RUNNER = 'path.to.my.module.MyTestRunner'
TEST_DISCOVER_TOP_LEVEL = BASE_DIR / 'tests/unit_and_integration_tests'

what magic is "django-admin startapp" doing, that the test runner needs to find my tests.py

I was having a problem that the django test runner wasn't finding the tests for my app, like this one:
Django test runner not finding tests
One of the comments on that thread suggested creating a new app with django-admin.py and seeing if the tests ran there. e.g.
django-admin.py startapp delme
then
adding "delme" to my INSTALLED_APPS
then
copying my tests.py from the app where it wasn't getting found into delme/
and viola! the tests did run. So, OK, I have a work arround, but I don't understand. I re-read what I think should be the relevant parts of the django documentation but the penny refuses to drop.
BTW, the app works via runserver and wsgi, so there doesn't appear to be any gross configuration problem. And my tests all pass from their new home, so I obviously need more tests :)
Specifically, I'm running django in a virtualenv, so I had run "django-admin.py startapp" in the (activated) virtualenv where I wanted the tests to run. This doesn't make the tests run in my other virtualenvs, I still have the old symptoms there (Ran 0 tests). I have a multitude of virtualenvs, managed by non-trivial paver scripts. One uses "path.copytree" for deploying projects, rewrites apache config files, restarts apache, writes wsgi files using the appropriate virtualenv, etc. The other uses PIP/GCC/aptitude/etc for bootstrapping/tearing down the different environments, updating packages as per configuration, etc. So I want to understand the difference between django-startapp and simply copying files, so I can fix these paver scripts so the tests can run in any environment I want them to.
The only thing that makes sense to me, after reading your description, is the location of paths for your existing apps. Can you confirm the following things:
Your app is at the same folder level as the delme app
Your app folder contains an __init__.py file
Your app is listed in the INSTALLED_APPS setting
I'm going to guess that it's a missing __init__.py file, as that trips some people up. To answer your specific question, django-admin startapp doesn't do anything magical. It just creates the right folders and files in the correct place.
Your folder structure should be...
my_project/
__init__.py
manage.py
settings.py
my_app/
__init__.py
tests.py
models.py
delme/
__init__.py
tests.py
models.py
Also note this comment
You can't easily name the TestCase class directly. You name the app, the Django runner does it's discovery thing by looking in models.py and tests.py
solved (still with a little whiff of magic).
diff showed that my old app didn't have a models.py but the new app ("delme", working) did. I didn't think the old app needed one, it was importing all it's domain classes from other places.
Touching an empty models.py in my old app fixed it, now the test runner finds the tests.py and everything works as expected. Condlusion - if an app has no models.py, the django test runner won't find the app's tests.py.
What I said about not working in different virtualenvs was bogus (red herring), I was a bit confused about what my deploy scripts were doing.

Cannot start any django app

I am a newbie at Django and everytime I try to run
python panel/manage.py startapp %app% (panel is my project) it gives me the error:
Error: '%app%' conflicts with the name of an existing Python module and cannot be used as an app name. Please try another name.
Am I doing something wrong?
Surely companies or contacts or stats is not the name of an existing Python module?
This is a fun one - your project and your app need to have different names. You probably created a project, then tried to startapp with the same name.
I was confused as well, until I realized that a Django project is a container for applications; this sequence makes it a bit clearer:
# first create a Project (container).
django-admin.py startproject Project
# create multiple apps
cd Project
python manage.py startapp polls
python manage.py startapp hello
...
Perhaps you need to
cd panel
python manage.py startapp yourappname
I'm not sure running the command from a directory above your project will work properly.
I had the same issue because I was trying to "restart" my app after carrying out changes, but startapp is meant to be used once to create a new app. To view changes, syncronize app with DB with python manage.py migrate and restart the server with python manage.py runserver instead.
From the django-admin docs
(manage.py does essentially the same thing as django-admin)
startapp <app_label> [destination]
django-admin startapp
Creates a Django app directory structure for
the given app name in the current directory or the given destination.
By default the directory created contains a models.py file and other
app template files. (See the source for more details.) If only the app
name is given, the app directory will be created in the current
working directory.
If the optional destination is provided, Django will use that existing
directory rather than creating a new one. You can use ‘.’ to denote
the current working directory.
For example:
django-admin startapp myapp /Users/jezdez/Code/myapp
This message is displayed if you run "startapp" twice with the same app name. As pointed out above by the OP it doesn't reload the app, it creates one.
You should choose different names for your project and app in Codes:
django-admin startproject **my_project**
python manage.py startapp **my_app**
You need to create the directory before using the commands. Suppose you want a polls app inside apps folder.
mkdir apps apps/polls
python manage.py startapp polls apps/polls
I guess maybe you have already created the app's dir in panel dir manually. The command 'startapp' is to create an app automatically. If you already have one there, it fails.
I reproduced the issue and there's actually something not working as I expected.
I wonder if we stumbled upon a Django's bug, or a limitation that I don't understand.
Having a project called "project" and an empty folder app/newapp
…I tried:
python manage.py startapp newapp apps/newapp
It returns:
CommandError: 'newapp' conflicts with the name of an existing Python module and cannot be used as an app name. Please try another name.
But if I target ANY other route in which the last folder is not called the same name as the app I'm starting, it works.
So I ended up doing:
python manage.py startapp newapp apps/main
Using Django 2.1.3.
if you want to make an empty directory that will contain your new app
project-dir
└── blog
├── __init__.py
├── ...
├── blog-ext #this empty dir that will contain the new app
└── views.py
so instead of typing :
python manage.py newapp blog/blog-ext
it should be :
django-admin startapp newapp blog/blog-ext
Try classic "mysite" or "myproject". You can delete it anytime you want, so if it will accepted, then all your privious ideas conflict with Python modules.
Edit: I tried all your ideas, there was no error for me. So, if you installed support libraries or modules for django, then some of them can contains such names.
this error is because of the name conflicts between the app name and project name.you had given same name for your app and project .your project and app need to be different name .if you had given the same name the above mentioned error will occur .
understand the difference between app and project
Projects vs. apps
What’s the difference between a project and an app? An app is a Web application that does something – e.g., a Weblog system, a database of public records or a simple poll app. A project is a collection of configuration and apps for a particular Web site. A project can contain multiple apps. An app can be in multiple projects.
first create the project.
then create the app.
NOTE: name for app and project should be different
first create a project with projectname
django-admin.py startproject Projectname .
Then create app with appname. (to create your app make sure you are in the same directory manage.py and type this command)
python manage.py startapp Appname
It's the process how I got my doubt clear.
First, I created a directory inside my project directory and put __init__.py, models.py, admin.py, apps.py & views.py.
Then I ran python manage.py runserver & It work well.
Then as suggested on that page I used startapp command. I got this error :
CommandError: 'ucportal' conflicts with the name of an existing Python
module and cannot be used as an app name. Please try another name.
After that I deleted that directory and ran startapp command with same name and it worked fine.
So 'startapp' command is to create an app automatically. If you already have one there, it fails.
Answer given by #DAG worked for me.
I ran into this issue while trying to set up a Wagtail project.
Before creating the app, I had created and activated a virtualenv (using virtualenvwrapper) with the same name: $APPNAME. When I then ran wagtail start $APPNAME, Django looks for naming conflics in the $PYTHONPATH which in this instance points to /Users/User/.virtualenvs.
Naturally, this results in a conflict as /Users/User/.virtualenvs/$APPNAME already exists.
None of these answers helped me. In the end I ended up creating an app with a different name and then just renaming the directory to the app name I wanted all along. Note that you also will need to change the class name in apps.py to match your app name.
Just Simply Use This command
for Django Project Creation
python -m django startproject name_of_django_Project
for Django App Creation
python -m django startapp App_name
I had the same issue when working with wagtail cms. I got this error even there is no such a created app. This occurs when there is an app already that has the same name you need to create inside the site-packages directory.
Once you get this error, you need to check the following directory,
C:\Users\{user}\AppData\Local\Programs\Python\Python38-32\Lib\site-packages
If there is a package with the name same you want to create then you need to remove that package. Also make sure to check that package is important or not before deleting.
The application directory should be created first.
Example: apps/practice
The command appears to be duplicated, but it is correct.
Example: python manage.py startapp practice ./apps1/practice