Unittest для setup.py - PullRequest
       8

Unittest для setup.py

0 голосов
/ 07 мая 2018

У меня есть следующее приложение Python:

.
├── application
│   ├── __init__.py
│   ├── code
│   │   ├── ...
│   └── test
│       ├── ...
└── setup.py

setup.py может использоваться для установки application. Кроме того, setup.py можно использовать для запуска юнит-тестов, которые находятся в application/test

Теперь я хочу создать юнит-тест в application/test, который пытается установить приложение и завершается неудачно, если его невозможно установить.

Мой код для такого юнит-теста:

import unittest
import os


class TestInstallation(unittest.TestCase):

    def test_installation(self):
        os.system('virtualenv --python=python3 ENV')
        os.system('source ENV/bin/activate')

        # install application
        os.system('python setup.py install')
        self.assertTrue('application' in os.system('pip list'))

        os.system('deactivate')
        os.system('rm -rf ENV')

Однако это не работает, поскольку каждая команда выполняется отдельно. (т.е. после того, как вы выполните команду для запуска виртуальной среды, вы немедленно выйдете из этой среды).

Это приводит к вопросу о том, что является хорошей альтернативой для проверки возможности успешной установки приложения. Это можно сделать в Python или только с помощью команд оболочки?

Заранее спасибо,

Patrick

1 Ответ

0 голосов
/ 15 мая 2018

Активация venv - это не что иное, как адаптация PATH и PYTHONHOME в оболочке, поэтому вы используете правильные исполняемые файлы из этого venv. Если вы явно указываете путь к исполняемым файлам, вам не нужно запускать ENV/bin/activate. Например, последовательность команд

$ virtualenv ENV --python=python3
$ source ENV/bin/activate
$ python setup.py install
$ pip list
$ deactivate

эквивалентно последовательности

$ virtualenv ENV --python=python3
$ ENV/bin/python setup.py install
$ ENV/bin/pip list

Вы можете использовать это в своем тесте. Дополнительно я бы:

  • перенесите создание и удаление ENV в настройке / разборке класса теста, чтобы в реальном тесте было меньше шума. Кроме того, tearDown обеспечит удаление вашего venv даже в случае сбоя test_installation;
  • замените os.system использование на subprocess, так как оно возвращает гораздо более хороший объект результата для проверки;
  • запустите команды с stdout=subprocess.PIPE для захвата напечатанных строк (также, чтобы они не загромождали результаты теста);
  • используйте pip list --format=freeze, чтобы вы могли проверить имя и версию пакета.

Однако это все необязательно, и вам не обязательно следовать этому примеру.

Вот как я бы адаптировал тест:

import shutil
import subprocess
import unittest


class TestInstallation(unittest.TestCase):

    def setUp(self):
        subprocess.run(['virtualenv', 'ENV', '--python=python3'], 
                       stdout=subprocess.PIPE)
        self.python = 'ENV/bin/python3'
        self.pip = 'ENV/bin/pip3'

    def tearDown(self):
        shutil.rmtree('ENV')

    def test_installation(self):
        subprocess.run([self.python, 'setup.py', 'install'], 
                       stdout=subprocess.PIPE)
        # check the installation succeeded (process exited with a 0)
        self.assertEqual(result.returncode, 0)

        result = subprocess.run([self.pip, 'list', '--format=freeze'],
                                stdout=subprocess.PIPE,
                                universal_newlines=True)
        self.assertIn('application==0.1', result.stdout.split())
...