Here is the context: I am working on Django. I started coding features but stopped to set up the first unit tests.
I wanted to test my CustomUser class located in JoBooking.models.py in the test_models.py file. JoBooking is an app I created in my Django project.
So I did the import from JoParis.JoBookings.models import CustomUser.
When I run python manage.py test or pytest in the terminal, I encounter this error: ModuleNotFoundError: No module named 'JoParis.JoBooking'
I have configured the application (JoBooking) in settings.py... but nothing works.
The init.py files are present in the packages.
I did a simple test to check if the URL of my application returns an HTTP 200 response, and the test works, but I have to remove the import from JoParis.JoBookings.models import CustomUser. So the test file is found, but the problem comes from the import when I want to test my models.
I'm stuck. I don't understand this error. ModuleNotFoundError: No module named Just explain me what is this error please. Thanks
In test_models.py
from django.test import TestCase
from ...JoBooking.models import CustomUser
# test inscription avec données valides et obligatoires
class TestCreateUser(TestCase):
def test_create_user(self):
user = CustomUser.objects.create_user(
email='[email protected]',
password='password',
username='',
first_name='user',
last_name='test',
is_superuser=False,
is_staff=False
)
assert CustomUser.objects.filter(email='[email protected]').exists() # verifie si dans la BDD
assert user.first_name == 'user'
assert user.last_name == 'test'
assert user.is_superuser is False # verifie si attribut par défaut pris en compte
assert user.is_staff is False
# test inscription avec données non valides
# test connexion user avec True data
# test connexion user avec False data
# test qui verifie http response = 200
class TestUrl(TestCase):
def test_my_view(self):
response = self.client.get('http://127.0.0.1:8000/')
self.assertEqual(response.status_code, 200)
in setting.py
from pathlib import Path
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = x
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'JoBooking',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'JoParis.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, "JoBooking/templates/JoBooking")],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'JoParis.wsgi.application'
# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'OPTIONS': {
"read_default_file": 'C:\\Users\\murhe\\OneDrive\\Bureau\\EXAM JO\\my.cnf.txt',
},
}
}
# Password validation
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/5.0/topics/i18n/
LANGUAGE_CODE = 'fr-fr'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.0/howto/static-files/
STATIC_URL = '/static/'
# Default primary key field type
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
AUTH_USER_MODEL = 'JoBooking.CustomUser'
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'JoBooking.authbackends.EmailAuthBackend',
]
The error message
: (venv) PS C:\Users\murhe\PycharmProjects\StudiProject\JoParis> pytest
====================================================================== test session starts =======================================================================
platform win32 -- Python 3.11.1, pytest-8.0.1, pluggy-1.4.0
django: version: 5.0.2, settings: JoParis.settings (from ini)
rootdir: C:\Users\murhe\PycharmProjects\StudiProject\JoParis
configfile: pytest.ini
plugins: django-4.8.0
collected 0 items / 2 errors
============================================================================= ERRORS =============================================================================
________________________________________________________ ERROR collecting JoBooking/tests/test_models.py _________________________________________________________
ImportError while importing test module 'C:\Users\murhe\PycharmProjects\StudiProject\JoParis\JoBooking\tests\test_models.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
..\..\..\AppData\Local\Programs\Python\Python311\Lib\importlib\__init__.py:126: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
E ModuleNotFoundError: No module named 'JoParis.JoBooking'
_________________________________________________________ ERROR collecting JoBooking/tests/test_views.py _________________________________________________________
ImportError while importing test module 'C:\Users\murhe\PycharmProjects\StudiProject\JoParis\JoBooking\tests\test_views.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
..\..\..\AppData\Local\Programs\Python\Python311\Lib\importlib\__init__.py:126: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
E ModuleNotFoundError: No module named 'JoParis.JoBooking'
======================================================================== warnings summary ========================================================================
..\venv\Lib\site-packages\_pytest\config\__init__.py:1396
C:\Users\murhe\PycharmProjects\StudiProject\venv\Lib\site-packages\_pytest\config\__init__.py:1396: PytestConfigWarning: Unknown config option: PYTHONPATH
self._warn_or_fail_if_strict(f"Unknown config option: {key}\n")
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
==================================================================== short test summary info =====================================================================
ERROR JoBooking/tests/test_models.py
ERROR JoBooking/tests/test_views.py
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 2 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
================================================================== 1 warning, 2 errors in 0.68s ===============
in views.py '''
from django.shortcuts import render, redirect
from django.contrib.auth import login, logout
from .forms import Connexion
from django.contrib.auth.forms import UserCreationForm
from .models import CustomUser, Offre, Reservation, Commande
from .authbackends import EmailAuthBackend
from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404
import uuid
# méthode pour créer un formulaire d'inscription (utilisation du formulaire émit par django par défaut)
class CustomSignupForm(UserCreationForm):
class Meta:
model = CustomUser # ici on spécifie qu'on veut ce modèle personnalisé
fields = ('first_name', 'last_name', 'email')
#note : le password est automatiquement intégré dans ce form
# view pour la page d'accueil
def index(request):
return render(request, 'JoBooking/index.html')
# view pour la page des offres
def offres(request):
list_offres = Offre.objects.all() # affiche toutes les offres = plan solo,duo,family ou autre
context = {'offres': list_offres}
return render(request, 'JoBooking/offres.html', context)
# view pour la page d'inscription
def inscription(request):
context = {} # stockage données lors du rendu de page
if request.method == 'POST': # vérification methode de la requête est POST = formulaire soumis
form = CustomSignupForm(request.POST) # création formulaire avec données POST
if form.is_valid(): # vérification de la validité des données
user = form.save() # sauvegarde dans la BDD
user.cle_inscription = uuid.uuid4().hex
user.save()
return redirect('inscription_reussie') # redirection de l'utilisateur vers une autre page
else:
context['errors'] = form.errors # erreur de validation
form = CustomSignupForm() # nouvelle page d'inscription vide donc sans POST
context['form'] = form
return render(request, 'JoBooking/inscription.html', context=context) # renvoie page d'inscription
# view pour l'inscripion réussie d'un user
def inscription_reussie(request):
return render(request, 'inscription_reussie.html')
# view pour la page de connexion
def connexion(request):
message = ""
if request.method == 'POST':
form = Connexion(request.POST) # création formulaire avec données envoyées via POST
if form.is_valid(): # vérification de la validité des données
email = form.cleaned_data['email'] # données nettoyées et récupérées
password = form.cleaned_data['password']
custom_auth = EmailAuthBackend() # implémentation de l'authentification personnalisée
user = custom_auth.authenticate(request, email=email, password=password) # appel de la méthode authenticate
# email = request.POST.get('email')
# password = request.POST.get('password')
if user is not None and password is not None: # signification : si l'user a été trouvée ...
login(request, user, backend='JoBooking.authbackends.EmailAuthBackend') # ya 2 backends d'auth
message = f'Bienvenue {user.first_name} ! Vous êtes connecté.'
return redirect('/') # redirige vers la page d'acceuil
else:
message = 'Identifiants non valides.'
return render(request, 'connexion.html',
context={'message': message}) # user non trouvé, donc retourne page connexion
else:
form = Connexion()
return render(request, 'connexion.html', context={'form': form, 'message': message})
# méthode pour que les users se déconnecte
def deconnexion(request):
logout(request)
return redirect('index')
# méthode pour ajouter à réservation. ( réservation c'est le panier. J'ai volontairement choisi ce terme)
def ajouter_reservation(request, offre_id):
user = request.user
offre = get_object_or_404(Offre, id=offre_id) # ici on récupère l'offre si inexistante,erreur 404
reservation, _ = Reservation.objects.get_or_create(user=user) # récupération du panier
commande, created = Commande.objects.get_or_create(user=user,
offre=offre) # récupération commande
if created: # exemple: une offre n'est pas dans la commande donc elle sera crée
reservation.commandes.add(commande)
reservation.save()
else: # l'offre est deja dans la commande donc on augmente la quantité
commande.quantity += 1
commande.save()
return redirect('offres')
# renvoie à la page de reservation (c'est la page panier, après avoir réserver)
@login_required(login_url='connexion') # connexion nécessaire pour avoir accès a cette page
def reservation(request):
reservation = get_object_or_404(Reservation, user=request.user)
return render(request, 'reservation.html', context={
'commandes': reservation.commandes.all()}) # affiche tous les éléments qu'ya dans la réservation
# methode pour annuler une réservation au complet
def annulation(request):
user_reservation = Reservation.objects.get(user=request.user)
if user_reservation: # si elle existe
user_reservation.commandes.all().delete()
user_reservation.delete() # suppression de tout ce qu'y a dans la réservation qu'on supprime ensuite
return redirect('index') # retourne vers la page d'accueil
def payer(request):
reservation = request.user.reservation
# génération de billets (combinaison des deux clés générées , qr code, nom acheteur + logo ;date de l'evement )
# augmentation de ventes de Offre selon la quantité achetée
for commande in reservation.commandes.all():
offre = commande.offre # récupration du plan dans la commande
offre.ventes += commande.quantity
offre.save()
# paiement dans Reservation devient TRUE (initialement à FALSE)
reservation.paiement = True
reservation.save()
# génération de clé unique pour paiment seulement si payer.
if reservation.paiement == True:
cle_paiement = uuid.uuid4().hex
reservation.cle_paiement = cle_paiement
reservation.save()
# le panier (réservation ) est réinitialisé
reservation.commandes.clear()
# Renvoie à la page de remerciement où on peut telecharger billet
return redirect('remerciements')
def remerciements(request):
return render(request, 'remerciements.html')
'''
in test_views.py
'''
from django.test import TestCase
from ...JoBooking.models import CustomUser
class TestUrl(TestCase):
def test_my_view(self):
response = self.client.get('http://127.0.0.1:8000/')
self.assertEqual(response.status_code, 200)
'''
another way to test
(venv) PS C:\Users\murhe\PycharmProjects\StudiProject\JoParis> python manage.py test JoBooking
Found 1 test(s).
System check identified no issues (0 silenced).
E
======================================================================
ERROR: JoParis.JoBooking (unittest.loader._FailedTest.JoParis.JoBooking)
----------------------------------------------------------------------
ImportError: Failed to import test module: JoParis.JoBooking
Traceback (most recent call last):
File "C:\Users\murhe\AppData\Local\Programs\Python\Python311\Lib\unittest\loader.py", line 440, in _find_test_path
package = self._get_module_from_name(name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\murhe\AppData\Local\Programs\Python\Python311\Lib\unittest\loader.py", line 350, in _get_module_from_name
__import__(name)
ModuleNotFoundError: No module named 'JoParis.JoBooking'
General answer :-
Try like below.
You should use relative paths to import from other scripts. In
JoParis.JoBookings.modelsJoParisis the folder name/project nameJoBookingsis the app name /app folder name(inside project folder)modelsis the python file name(inside app folder).Which all are relative to current (importing statement) file.
So, to import like above,
JoParisshould be a sub folder from the current test script.Insight upon new info regarding the problem :-
For
C:\Users\murhe\PycharmProjects\StudiProject\JoParis\JoBooking\tests\test_models.pylocation, try like below.More info :-
link 1
link 2
Django tests :-
Look here for how to run tests