Uruchamianie unittest z typową strukturą katalogów testowych
Bardzo powszechną strukturą katalogów nawet dla prostego modułu Pythona wydaje się być oddzielenie testów jednostkowych do ich własnego katalogu test
:
new_project/
antigravity/
antigravity.py
test/
test_antigravity.py
setup.py
etc.
Na przykład zobacz to Python project howto .
Moje pytanie brzmi po prostu jaki jest zwykły sposób przeprowadzania testów? podejrzewam, że jest to oczywiste dla wszystkich oprócz mnie, ale nie możesz po prostu uruchomić python test_antigravity.py
z katalogu testowego, ponieważ jego import antigravity
nie powiedzie się, ponieważ moduł nie znajduje się na ścieżce.
I know I może zmodyfikować PYTHONPATH i inne sztuczki związane ze ścieżką wyszukiwania, ale nie mogę uwierzyć, że jest to najprostszy sposób - jest w porządku, jeśli jesteś programistą, ale nie realistycznie oczekiwać, że użytkownicy będą używać, jeśli chcą tylko sprawdzić, czy testy przechodzą.
Inną alternatywą jest po prostu skopiowanie pliku testowego do innego katalogu, ale wydaje się to nieco głupie i pomija sens posiadania ich w osobnym katalogu na początek.
Więc, gdybyś właśnie ściągnął źródło do mojego nowego projektu jak przeprowadziłbyś testy jednostkowe? Wolałbym odpowiedź, która pozwoliłaby mi powiedzieć moim użytkownikom: "aby uruchomić testy jednostkowe do X."
16 answers
Moim zdaniem najlepszym rozwiązaniem jest użycie unittest
interfejs wiersza poleceń, który doda katalog do sys.path
, więc nie musisz (robione w klasie TestLoader
).
Na przykład dla struktury katalogów takiej jak ta:
new_project
├── antigravity.py
└── test_antigravity.py
Możesz po prostu uruchomić:
$ cd new_project
$ python -m unittest test_antigravity
Dla struktury katalogów takiej jak twoja:
new_project
├── antigravity
│ ├── __init__.py # make it a package
│ └── antigravity.py
└── test
├── __init__.py # also make test a package
└── test_antigravity.py
I w modułach testowych wewnątrz pakietu test
, można zaimportować pakiet antigravity
i jego moduły jako Zwykle:
# import the package
import antigravity
# import the antigravity module
from antigravity import antigravity
# or an object inside the antigravity module
from antigravity.antigravity import my_object
Uruchomienie pojedynczego modułu testowego:
Aby uruchomić pojedynczy moduł testowy, w tym przypadku test_antigravity.py
:
$ cd new_project
$ python -m unittest test.test_antigravity
Po prostu odwołaj się do modułu testowego w ten sam sposób, w jaki go importujesz.
Uruchamianie pojedynczego przypadku testowego lub metody badania:
Możesz również uruchomić pojedynczą TestCase
lub pojedynczą metodę testową:
$ python -m unittest test.test_antigravity.GravityTestCase
$ python -m unittest test.test_antigravity.GravityTestCase.test_method
Uruchamianie wszystkich testów:
Możesz również użyć test discovery, który odkryje i uruchomi wszystkie testy dla Ciebie muszą być modułami lub pakietami o nazwie test*.py
(można je zmienić za pomocą znacznika -p, --pattern
):
$ cd new_project
$ python -m unittest discover
Spowoduje uruchomienie wszystkich test*.py
modułów wewnątrz test
pakietu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-23 08:49:11
Najprostszym rozwiązaniem dla użytkowników jest dostarczenie skryptu wykonywalnego (runtests.py
lub jakiegoś podobnego), który uruchamia niezbędne środowisko testowe, włączając w to, w razie potrzeby, dodanie katalogu głównego projektu do sys./ align = "left" / Nie wymaga to od użytkowników ustawiania zmiennych środowiskowych, coś takiego działa dobrze w skrypcie bootstrap:
import sys, os
sys.path.insert(0, os.path.dirname(__file__))
Wtedy instrukcje dla użytkowników mogą być tak proste ,jak "python runtests.py".
Oczywiście, jeśli ścieżka, której potrzebujesz naprawdę jest os.path.dirname(__file__)
, Python zawsze umieszcza katalog aktualnie uruchomionego skryptu na początku sys.path
, więc w zależności od struktury katalogów może być wszystko, co jest potrzebne, po prostu zlokalizowanie runtests.py
we właściwym miejscu.
Ponadto moduł unittest w Pythonie 2.7+ (który jest backportowany jako unittest2 dla Pythona 2.6 i wcześniejszych) ma teraz wbudowane wykrywanie testów , więc nos nie jest już potrzebny, jeśli chcesz zautomatyzować test discovery: instrukcje użytkownika mogą być tak proste jak "python-m unittest discover".
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-23 05:15:30
Zazwyczaj tworzę skrypt " uruchom testy "w katalogu projektu (tym, który jest wspólny zarówno dla katalogu źródłowego, jak i test
), który ładuje mój pakiet" wszystkie testy". Zazwyczaj jest to kod boilerplate, więc mogę go ponownie użyć od projektu do projektu.
Run_tests.py:
import unittest
import test.all_tests
testSuite = test.all_tests.create_test_suite()
text_runner = unittest.TextTestRunner().run(testSuite)
Test/all_tests.py (from Jak uruchomić wszystkie testy jednostkowe Pythona w katalogu?)
import glob
import unittest
def create_test_suite():
test_file_strings = glob.glob('test/test_*.py')
module_strings = ['test.'+str[5:len(str)-3] for str in test_file_strings]
suites = [unittest.defaultTestLoader.loadTestsFromName(name) \
for name in module_strings]
testSuite = unittest.TestSuite(suites)
return testSuite
Dzięki tej konfiguracji możesz rzeczywiście po prostu include antigravity
w swoich modułach testowych. Minusem jest to, że potrzebujesz więcej kod wsparcia do wykonania konkretnego testu... Sprawdzam je za każdym razem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:02
Z artykułu, do którego podlinkowałeś:
Create a test_modulename.py plik i umieść w nim swoje najmocniejsze testy. Od Moduły testowe znajdują się w oddzielnym katalog z twojego kodu, możesz potrzebować aby dodać Katalog nadrzędny modułu do twojego PYTHONPATH, aby uruchomić them:
$ cd /path/to/googlemaps $ export PYTHONPATH=$PYTHONPATH:/path/to/googlemaps/googlemaps $ python test/test_googlemaps.py
Wreszcie jest jeszcze jeden popularny unit testing framework for Python (to takie ważne!), nos. nos pomaga uprościć i rozszerzyć wbudowany unittest framework (może, na przykład, automagicznie Znajdź swój test kod i skonfiguruj PYTHONPATH dla ty), ale nie jest on dołączony do standardowa Dystrybucja Pythona.
Może powinieneś spojrzeć na nos Jak to sugeruje?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-13 16:25:43
Jeśli uruchomisz "python setup.py develop" wtedy pakiet będzie na ścieżce. Ale możesz nie chcieć tego robić, ponieważ możesz zainfekować instalację Pythona systemowego, dlatego istnieją narzędzia takie jak virtualenvi buildout.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-13 16:27:00
Miałem ten sam problem, z oddzielnym folderem testów jednostkowych. Ze wspomnianych sugestii dodaję absolutną ścieżkę źródłową do sys.path
.
Zaletą następującego rozwiązania jest to, że można uruchomić plik {[2] } bez zmiany na początku do katalogu testowego:
import sys, os
testdir = os.path.dirname(__file__)
srcdir = '../antigravity'
sys.path.insert(0, os.path.abspath(os.path.join(testdir, srcdir)))
import antigravity
import unittest
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-25 08:41:44
Użyj setup.py develop
, aby twój katalog roboczy stał się częścią zainstalowanego środowiska Pythona, a następnie uruchom testy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-13 16:24:53
Jeśli używasz VS Code, a twoje testy znajdują się na tym samym poziomie co twój projekt, uruchamianie i debugowanie kodu nie działa po wyjęciu z pudełka. Możesz zmienić swój start.plik json:
{
"version": "0.2.0",
"configurations": [
{
"name": "Python",
"type": "python",
"request": "launch",
"stopOnEntry": false,
"pythonPath": "${config:python.pythonPath}",
"program": "${file}",
"cwd": "${workspaceRoot}",
"env": {},
"envFile": "${workspaceRoot}/.env",
"debugOptions": [
"WaitOnAbnormalExit",
"WaitOnNormalExit",
"RedirectOutput"
]
}
]
}
Kluczowy wiersz to envFile
"envFile": "${workspaceRoot}/.env",
W korzeniu twojego projektu Dodaj .plik env
Wewnątrz twojego .plik env Dodaj ścieżkę do katalogu głównego projektu. To tymczasowo dodaPYTHONPATH = C: \ YOUR \ PYTHON \ PROJECT \ ROOT_DIRECTORY
Ścieżka do twojego projektu i będziesz mógł użyć testów jednostkowych z VS Code
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-28 00:38:45
Rozwiązanie / przykład dla modułu unittest Pythona
Biorąc pod uwagę następującą strukturę projektu:
ProjectName
├── project_name
| ├── models
| | └── thing_1.py
| └── __main__.py
└── test
├── models
| └── test_thing_1.py
└── __main__.py
Możesz uruchomić swój projekt z katalogu głównego za pomocą python project_name
, który wywołuje ProjectName/project_name/__main__.py
.
Aby przeprowadzić testy z python test
, efektywnie uruchamiając ProjectName/test/__main__.py
, musisz wykonać następujące czynności:
1) Zmień swój katalog test/models
W pakiet, dodając plik __init__.py
. To sprawia, że przypadki testowe w podkatalogu są dostępne z poziomu rodzica test
katalog.
# ProjectName/test/models/__init__.py
from .test_thing_1 import Thing1TestCase
2) zmodyfikuj ścieżkę systemową w test/__main__.py
, aby dołączyć do katalogu project_name
.
# ProjectName/test/__main__.py
import sys
import unittest
sys.path.append('../project_name')
loader = unittest.TestLoader()
testSuite = loader.discover('test')
testRunner = unittest.TextTestRunner(verbosity=2)
testRunner.run(testSuite)
Teraz możesz z powodzeniem importować rzeczy z project_name
w swoich testach.
# ProjectName/test/models/test_thing_1.py
import unittest
from project_name.models import Thing1 # this doesn't work without 'sys.path.append' per step 2 above
class Thing1TestCase(unittest.TestCase):
def test_thing_1_init(self):
thing_id = 'ABC'
thing1 = Thing1(thing_id)
self.assertEqual(thing_id, thing.id)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-28 23:45:13
Oto moja struktura projektu:
ProjectFolder:
- project:
- __init__.py
- item.py
- tests:
- test_item.py
Uznałem, że lepiej zaimportować w metodzie setUp ():
import unittest
import sys
class ItemTest(unittest.TestCase):
def setUp(self):
sys.path.insert(0, "../project")
from project import item
# further setup using this import
def test_item_props(self):
# do my assertions
if __name__ == "__main__":
unittest.main()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-25 14:01:44
Jak zwykle przeprowadza się testy
Używam Pythona 3.6.2
cd new_project
pytest test/test_antigravity.py
Aby zainstalować : sudo pip install pytest
Nie ustawiłem żadnej zmiennej path i mój Import nie zawodzi z tą samą" testową " strukturą projektu.
Skomentowałem to: if __name__ == '__main__'
tak:
Test_antigravity.py
import antigravity
class TestAntigravity(unittest.TestCase):
def test_something(self):
# ... test stuff here
# if __name__ == '__main__':
#
# if __package__ is None:
#
# import something
# sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
# from .. import antigravity
#
# else:
#
# from .. import antigravity
#
# unittest.main()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-26 21:55:33
Zauważyłem, że jeśli uruchomisz interfejs wiersza poleceń unittest z katalogu "src", import działa poprawnie bez modyfikacji.
python -m unittest discover -s ../test
Jeśli chcesz umieścić to w pliku wsadowym w katalogu projektu, możesz to zrobić:
setlocal & cd src & python -m unittest discover -s ../test
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-07 23:13:39
Możliwe jest użycie wrappera, który uruchamia wybrane lub wszystkie testy.
Na przykład:
./run_tests antigravity/*.py
Lub aby uruchomić wszystkie testy rekurencyjnie użyj globbing (tests/**/*.py
) (enable by shopt -s globstar
).
Wrapper może w zasadzie używać argparse
do parsowania argumentów takich jak:
parser = argparse.ArgumentParser()
parser.add_argument('files', nargs='*')
Następnie załaduj wszystkie testy:
for filename in args.files:
exec(open(filename).read())
Następnie dodaj je do swojego zestawu testów (używając inspect
):
alltests = unittest.TestSuite()
for name, obj in inspect.getmembers(sys.modules[__name__]):
if inspect.isclass(obj) and name.startswith("FooTest"):
alltests.addTest(unittest.makeSuite(obj))
I uruchom je:
result = unittest.TextTestRunner(verbosity=2).run(alltests)
Sprawdź ten przykład więcej szczegóły.
Zobacz także: Jak uruchomić wszystkie testy jednostkowe Pythona w katalogu?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-30 13:13:06
Ten skrypt BASH uruchomi testowy katalog unittest Pythona z dowolnego miejsca w systemie plików, bez względu na to, w jakim katalogu roboczym się znajdujesz.
Jest to przydatne podczas pobytu w katalogu roboczym ./src
lub ./example
i potrzebujesz szybkiego testu jednostkowego:
#!/bin/bash
this_program="$0"
dirname="`dirname $this_program`"
readlink="`readlink -e $dirname`"
python -m unittest discover -s "$readlink"/test -v
Nie ma potrzeby, aby plik test/__init__.py
obciążał Twój Pakiet / narzut pamięci podczas produkcji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-13 00:50:04
Python 3 +
dodawanie do @ Pierre
Używanie unittest
struktury katalogów w ten sposób:
new_project
├── antigravity
│ ├── __init__.py # make it a package
│ └── antigravity.py
└── test
├── __init__.py # also make test a package
└── test_antigravity.py
Aby uruchomić moduł testowy test_antigravity.py
:
$ cd new_project
$ python -m unittest test.test_antigravity
Lub pojedynczy TestCase
$ python -m unittest test.test_antigravity.GravityTestCase
Obowiązkowe nie zapomnij __init__.py
nawet jeśli puste inaczej nie zadziała.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-08 15:12:19
Naprawdę powinieneś użyć narzędzia pip.
Użyj pip install -e
, aby zainstalować pakiet w trybie deweloperskim. To bardzo dobra praktyka.
W podanym poniżej adresie URL Ref podano 2 klasyczny układ projektu (z testem), możesz śledzić dowolny z nich.
Ref :
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:40