0

I created a GUI that accepts input arguments when starting this is a minimum working example that I am currently using for testing.

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
import os
import argparse
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QCoreApplication, QObject, Qt
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import *

def erase_data(argv):
    # print(args)
    if argv.erase_data:
        folders = ["scratch"]
        for folder in folders:
            try:
                os.unlink(folder + os.sep + "file1.pkl")
                os.unlink(folder + os.sep + "file2.txt")
            except FileNotFoundError:
                print(f"no file found in {folder} to delete")
                return None
        return True
    return False

class Example(QMainWindow):
    def __init__(self, parent=None):
        super().__init__()
        self.initUI(self)
        

    def initUI(self, MainWindow):
        # centralwidget
        MainWindow.resize(346, 193)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        # The Action to quit
        self.toolb_action_Exit = QAction(QIcon("exit.png"), "Exit", self)
        self.toolb_action_Exit.setShortcut("Ctrl+Q")
        self.toolb_action_Exit.triggered.connect(self.close)

        # The Button
        self.btn_prt = QtWidgets.QPushButton(self.centralwidget)
        self.btn_prt.setGeometry(QtCore.QRect(120, 20, 89, 25))
        self.btn_prt.clicked.connect(lambda: self.doPrint())
        self.btn_quit = QtWidgets.QPushButton(self.centralwidget)
        self.btn_quit.setGeometry(QtCore.QRect(220, 20, 89, 25))
        self.btn_quit.clicked.connect(lambda: self.close())

        # The textEdit
        self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
        self.textEdit.setGeometry(QtCore.QRect(10, 60, 321, 81))

        # Show the frame
        MainWindow.setCentralWidget(self.centralwidget)
        print(args)
        erase_data(args)
        # self.show()

    def doPrint(self):
        print("TEST doPrint")

    def closeEvent(self, event):
        # Ask a question before to quit.
        self.replyClosing = QMessageBox.question(
            self,
            "Message",
            "Are you sure to quit?",
            QMessageBox.Yes | QMessageBox.No,
            QMessageBox.No,
        )

        if self.replyClosing == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()
def _str_to_bool(s):
    """Convert string to bool (in argparse context)."""
    if s.lower() not in ["true", "false"]:
        raise ValueError("Need bool; got %r" % s)
    return {"true": True, "false": False}[s.lower()]


def add_boolean_argument(parser, name, default=False):
    """Add a boolean argument to an ArgumentParser instance."""
    group = parser.add_mutually_exclusive_group()
    group.add_argument(
        "--" + name, nargs="?", default=default, const=True, type=_str_to_bool
    )
  
def set_argparse():
    parser = argparse.ArgumentParser(description="Run CORMAT_py")

    add_boolean_argument(parser, "erase_data")
    args = parser.parse_args(sys.argv[1:])
    return args

def main():
    app = QApplication(sys.argv)
    imageViewer = Example()
    
    return app, imageViewer


if __name__ == "__main__":
    args = set_argparse()
    app, imageViewer = main()
    imageViewer.show()
    rc = app.exec_()
    print("App end is exit code {}".format(rc))
    sys.exit(rc)

now I am trying to unittest a function that uses one of the passed arguments following this question and I wrote this unit test

import logging
import os
import pathlib
import sys
import pytest

from GUI import erase_data
from unittest import mock

logger = logging.getLogger(__name__)

sys.path.append(os.getcwd())
src_dir = pathlib.Path(__file__).parents[1].absolute()
print(src_dir)
sys.path.append(src_dir.as_posix())
from GUI import main

logger = logging.getLogger(__name__)


@pytest.mark.parametrize("argv, called, response", [
    ([], True, False),
    (['--erase_data'], True, None),
    (['--noerase_data'], True, False),
])
def test_erase_data_nodata(argv, called, response):
    global erase_data
    original_erase_data = erase_data
    erase_data = mock.Mock(return_value=response)
    with mock.patch('sys.argv', [''] + argv):
        main()

        assert erase_data.called == called
    erase_data = original_erase_data

pytest.main('-x tests/test_args.py'.split())

that gets me a NameError as 'args' in the test is not defined and also a seg fault.

how to solve it?

bruvio
  • 853
  • 1
  • 9
  • 30

0 Answers0