Select Git revision
test_publish.py
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
test_publish.py 8.69 KiB
# -*- coding: utf-8 -*-
"""
Unittests for publish
"""
import unittest
import os
import sys
import platform
import shutil
from subprocess import run, CalledProcessError
from unittest.mock import patch
import matplotlib.pyplot as plt
from plotid.publish import publish
SRC_DIR = 'test_src_folder'
SRC_FILES = ['test_file1.txt', 'test_file2.jpg', 'test_file3.exe']
PIC_NAME = 'test_picture'
DST_DIR = 'test_dst_folder'
DST_PARENT_DIR = 'test_parent'
DST_PATH = os.path.join(DST_PARENT_DIR, DST_DIR)
INVISIBLE_PATH = os.path.join(DST_PARENT_DIR, '.' + DST_DIR)
FIG = plt.figure()
FIG2 = plt.figure()
FIGS_AS_LIST = [FIG, FIG2]
PIC_NAME_LIST = [PIC_NAME, 'second_picture']
class TestPublish(unittest.TestCase):
"""
Class for all unittests of the publish module.
"""
def setUp(self):
""" Generate source and destination directory and source files. """
os.makedirs(SRC_DIR, exist_ok=True)
os.makedirs(DST_PARENT_DIR, exist_ok=True)
for file in SRC_FILES:
open(file, 'w', encoding='utf-8').close()
# Skip test if tests are run from command line.
@unittest.skipIf(not os.path.isfile(sys.argv[0]), 'Publish is not called '
'from a Python script. Therefore, the script cannot be '
'copied.')
def test_publish(self):
""" Test publish and check if an exported picture file exists. """
publish(SRC_DIR, DST_PATH + '/', FIG, PIC_NAME, 'individual')
assert os.path.isfile(os.path.join(DST_PATH, PIC_NAME + '.png'))
# Skip test if tests are run from command line.
@unittest.skipIf(not os.path.isfile(sys.argv[0]), 'Publish is not called '
'from a Python script. Therefore, the script cannot be '
'copied.')
def test_publish_multiple_figs(self):
"""
Test publish with multiple figures and check if all exported picture
files exist.
"""
publish(SRC_DIR, DST_PATH, FIGS_AS_LIST, PIC_NAME_LIST, 'individual')
for name in PIC_NAME_LIST:
assert os.path.isfile(os.path.join(DST_PATH, name + '.png'))
def test_publish_multiple_src_files(self):
"""
Test publish with multiple source files and check
if the exported data files exist.
"""
files_and_dir = list(SRC_FILES)
files_and_dir.append(SRC_DIR)
publish(files_and_dir, DST_PATH, FIGS_AS_LIST, PIC_NAME_LIST,
'individual')
assert os.path.isdir(DST_PATH)
for file in SRC_FILES:
assert os.path.isfile(os.path.join(DST_PATH, file))
def test_src_directory(self):
""" Test if Error is raised when source directory does not exist."""
with self.assertRaises(FileNotFoundError):
publish('not_existing_folder', DST_PATH, FIG,
PIC_NAME, 'individual')
def test_src_directory_type(self):
""" Test if Error is raised when source directory is not a string."""
with self.assertRaises(TypeError):
publish([SRC_DIR, 4], DST_PATH, FIG, PIC_NAME, 'individual')
with self.assertRaises(TypeError):
publish(4, DST_PATH, FIG, PIC_NAME, 'individual')
def test_dst_directory(self):
""" Test if Error is raised when destination dir does not exist."""
with self.assertRaises(FileNotFoundError):
publish(SRC_DIR, 'not_existing_folder',
FIG, PIC_NAME, 'individual')
def test_script_exists(self):
"""
Test if Error is raised when publish is called from a shell.
First publish is called from a python shell with correct parameters.
It is checked if the subprocess returns an Error. Since the type of
exception is not passed but a CalledProcessError is raised, publish
is called again and it is checked if the output contains the correct
exception type.
"""
if platform.system() == "Linux":
python = "python3"
else:
python = "python"
with self.assertRaises(CalledProcessError):
run([python, "-c",
"import matplotlib.pyplot as plt\n"
"from plotid.publish import publish\n"
"publish('test_src_folder', 'test_parent/test_dst_folder',"
" plt.figure(), 'test_picture')"],
capture_output=True, check=True)
process = run([python, "-c",
"import matplotlib.pyplot as plt\n"
"from plotid.publish import publish\n"
"publish('test_src_folder', "
"'test_parent/test_dst_folder', plt.figure(), "
"'test_picture')"],
capture_output=True)
assert ("FileNotFoundError: Cannot copy original python script. "
"Running publish from a shell"
" is not possible.") in process.stderr.decode()
# Skip test if tests are run from command line.
@unittest.skipIf(not os.path.isfile(sys.argv[0]), 'Publish is not called '
'from a Python script. Therefore, the script cannot be '
'copied.')
def test_dst_already_exists_yes(self):
"""
Test if publish succeeds if the user wants to overwrite an existing
destination directory.
"""
os.mkdir(DST_PATH)
# Mock user input as 'yes'
with patch('builtins.input', return_value='yes'):
publish(SRC_DIR, DST_PATH, FIG, PIC_NAME, 'individual')
# Skip test if tests are run from command line.
@unittest.skipIf(not os.path.isfile(sys.argv[0]), 'Publish is not called '
'from a Python script. Therefore, the script cannot be '
'copied.')
def test_dst_already_exists_no(self):
"""
Test if publish exits with error if the user does not want to overwrite
an existing destination directory by user input 'no'.
"""
os.mkdir(DST_PATH)
# Mock user input as 'no'
with patch('builtins.input', return_value='no'):
with self.assertRaises(RuntimeError):
publish(SRC_DIR, DST_PATH, FIG, PIC_NAME, 'individual')
# Skip test if tests are run from command line.
@unittest.skipIf(not os.path.isfile(sys.argv[0]), 'Publish is not called '
'from a Python script. Therefore, the script cannot be '
'copied.')
def test_dst_already_exists_empty(self):
"""
Test if publish exits with error if the user does not want to overwrite
an existing destination directory by missing user input.
"""
os.mkdir(DST_PATH)
# Mock user input as empty (no should be default).
with patch('builtins.input', return_value=''):
with self.assertRaises(RuntimeError):
publish(SRC_DIR, DST_PATH, FIG, PIC_NAME, 'individual')
# Skip test if tests are run from command line.
@unittest.skipIf(not os.path.isfile(sys.argv[0]), 'Publish is not called '
'from a Python script. Therefore, the script cannot be '
'copied.')
def test_dst_invisible_already_exists(self):
"""
Test if after a crash of publish the partially copied data is
removed.
To mock this, the invisible directory already exists.
"""
os.mkdir(INVISIBLE_PATH)
# Mock user input as 'yes'
with patch('builtins.input', return_value='yes'):
with self.assertRaises(RuntimeError):
publish(SRC_DIR, DST_PATH, FIG, PIC_NAME, 'individual')
assert not os.path.isdir(INVISIBLE_PATH)
def test_plot_names(self):
""" Test if Error is raised if plot_name is not a string. """
with self.assertRaises(TypeError):
publish(SRC_DIR, DST_PATH, FIG, 7.6, 'individual')
with self.assertRaises(TypeError):
publish(SRC_DIR, DST_PATH, FIG, (), 'individual')
with self.assertRaises(TypeError):
publish(SRC_DIR, DST_PATH, FIG, ['test', 3], 'individual')
def test_data_storage(self):
"""
Test if Error is raised when unsupported storage method was chosen.
"""
with self.assertRaises(ValueError):
publish(SRC_DIR, DST_PATH, FIG, PIC_NAME, 'none_existing_method')
with self.assertRaises(TypeError):
publish(SRC_DIR, DST_PATH, FIG, PIC_NAME, 3)
with self.assertRaises(TypeError):
publish(SRC_DIR, DST_PATH, FIG, PIC_NAME, [])
def tearDown(self):
""" Delete all files created in setUp. """
shutil.rmtree(SRC_DIR)
shutil.rmtree(DST_PARENT_DIR)
for file in SRC_FILES:
os.remove(file)
if __name__ == '__main__':
unittest.main()