Как получить доступ к выводу графического интерфейса?

Я разрабатываю один тестовый стенд, который запускает несколько тестов через графический интерфейс Python и печатает вывод, как показано ниже.

A Passed
B Passed
C Passed
D Passed
E Passed

Кнопка из графического интерфейса должна быть изменена на «Пройдено» только тогда, когда все A, B, C, D, E пройдены. Если какой-либо из этих тестов не пройден, он должен сказать, что он не пройден. Как получить доступ к этому выводу из графического интерфейса, который печатается на экране.

Мой код для тестов:

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys, os, time
from PyQt4 import QtGui, QtCore
from progress.bar import Bar
import datetime 
import thread

class MyTestBench(QDialog, QtGui.QWidget):
    def __init__(self):
        super(QDialog, self).__init__()
        self.setWindowTitle("Implementation")

        self.progressbar = QtGui.QProgressBar()
        self.progressbar.setMinimum(0)
        self.progressbar.setMaximum(100)
        self.run_test_button = QtGui.QPushButton('Run Your Tests')
        self.run_test_button.clicked.connect(self.run_test_event)

    def run_test_event(self):
        thread.start_new_thread(self.run_the_test, ("Thread-1", 0.5))
        thread.start_new_thread(self.run_the_progress, ("Thread-2", 0.5))


    def run_the_test(self, tname, delay):        
        os.system("python nxptest.py my_testlist.txt")
        self.progressbar.setValue(100)
        if self.progressbar.value() == self.progressbar.maximum(): 
            time.sleep(3)
            self.run_test_button.setText('Run Your Tests')


    def run_the_progress(self, tname, delay):
        count = 0
        while count < 5:
            self.run_test_button.setText('Running.')
            time.sleep(0.5)
            self.run_test_button.setText('Running..')
            time.sleep(0.5)
            self.run_test_button.setText('Running...')
            value = self.progressbar.value() + 10
            self.progressbar.setValue(value)
            time.sleep(0.5)
            if self.progressbar.value() == self.progressbar.maximum():
                self.progressbar.reset()
            count = count + 1

app = QApplication(sys.argv)
dialog = MyTestBench()
dialog.setGeometry(100, 100, 200, 50)
dialog.show()
app.exec_()

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


person tryPy    schedule 20.10.2014    source источник
comment
Тесты производят вывод только операторами печати?   -  person mdurant    schedule 20.10.2014
comment
@mdurant да, эта работа выполняется через модуль nxptest.py   -  person tryPy    schedule 20.10.2014


Ответы (2)


Если вы пытаетесь получить текстовый вывод программы, вы не можете запустить эту программу, используя os.system. Как сказано в документах для этой функции:

Модуль subprocess предоставляет более мощные средства для создания новых процессов и получения их результатов; использование этого модуля предпочтительнее использования этой функции. См. раздел Замена старых функций модулем subprocess в разделе < документацию href="https://docs.python.org/3/library/subprocess.html#module-subprocess" rel="nofollow">subprocess с некоторыми полезными рецептами.

Если вы перейдете по этим ссылкам, они покажут, как делать то, что вы хотите. Но в основном это примерно так:

output = subprocess.check_output(["python", "nxptest.py", "my_testlist.txt"])

Если вы используете версию 2.6 или более раннюю, у вас не будет check_output; вы можете прочитать документацию, чтобы узнать, как создать его самостоятельно, например, поверх communicate, или вы можете просто установить subprocess32 сделайте резервную копию из PyPI и используйте это.


Из комментария:

Это работает, но меня беспокоит только то, что есть много результатов для тестов, которые печатаются до того, как они на самом деле печатают A Passed B Passed и т. Д. Я ищу способ получить только эту часть строки, а не весь вывод.

Это невозможно. Как ваша программа могла понять, какая часть вывода является «этой частью строки», а какая — «множеством результатов… которые были напечатаны раньше»?

Если вы можете каким-то образом отредактировать тестируемые программы — например, заставить их печатать свой «настоящий» вывод в стандартный вывод, а «дополнительный» вывод — в стандартный вывод, или предоставить аргумент командной строки, который заставит их пропустить все лишнее — Замечательно. Но предполагая, что вы не можете, нет другой альтернативы, кроме как фильтровать результаты.

Но это выглядит не очень сложно. Если каждая строка «реального» вывода имеет значение "X Passed" или "X Failed" и больше ничего не начинается с "X " (где X — любая буква ASCII в верхнем регистре), это просто:

test_results = {}
for line in output.splitlines():
    if line[0] in string.ascii_uppercase and line[1] == ' ':
        test_results[line[0]] = line[2:]

Теперь, в конце, у вас есть:

{'A': 'Passed', 'B': 'Passed', 'C': 'Passed', 'D': 'Passed', 'E': 'Passed'}

Если вы хотите убедиться, что все AE были пройдены и все они прошли:

passed = (set(test_results) == set('ABCDE') and
          all(value == 'Passed' for value in test_results.values()))

Конечно, вы могли бы создать что-то более приятное, показывающее, какие из них были пропущены, не прошли или что-то в этом роде. Но, честно говоря, если вы хотите что-то более мощное, вам, вероятно, следует использовать существующую среду модульного тестирования, а не создавать ее с нуля.

person abarnert    schedule 20.10.2014
comment
@abarnet Спасибо. Это работает, но меня беспокоит только то, что есть много результатов тестов, которые печатаются до того, как они на самом деле печатают A Passed B Passed и т. д. Я ищу способ получить только эту часть строки, а не весь вывод. - person tryPy; 20.10.2014
comment
@tryPy: Затем вам нужно проанализировать вывод. Если вы не можете изменить тестируемую программу, чтобы она не смешивала реальный вывод с ненужными вещами, это невозможно обойти. - person abarnert; 20.10.2014

Вы можете замаскировать вывод на печать через очередь следующим образом:

class FileQ(Queue.Queue):
    def __init__(self):
        Queue.Queue.__init__(self)

    def write(self,data):
        self.put(data)

class MyTestBench(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.incoming = FileQ()
        self.setWindowTitle("Implementation")
        sys.stdout = self.incoming
        self.time = QtCore.QTimer()
        self.time.timeout.connect(self.refresh)
        self.time.start(10)
        self.t = QtGui.QTextEdit(self)
        self.t.setObjectName('TextOut')
        self.box = QtGui.QHBoxLayout(self)
        self.setLayout(self.box)
        self.box.addWidget(self.t)
        self.run_test_event()
        self.progressbar = QtGui.QProgressBar(self)
        self.progressbar.setObjectName('BarOut')
        self.box.addWidget(self.progressbar)

    def run_test_event(self):
        thread.start_new_thread(self.run_the_test, ("Thread-1", 0.5))

    def run_the_test(self,*args):
        for i in range(10):
            print i
            time.sleep(1)

    def refresh(self):        
        try:
            data = self.incoming.get_nowait()
        except:
            return
        if data:
            self.t.insertPlainText(str(data))
            self.progressbar.setValue(int(data)*10)
person mdurant    schedule 20.10.2014