index.lxp@lxpwrap=x5255_252ehtm.htm
来自「GUI Programming with Python」· HTM 代码 · 共 384 行
HTM
384 行
<table border="0" cellspacing="0" cellpadding="3" width="100%"><tr><td> <div align="center" id="bldcontent"> <a href="../default.htm"><img src="../images/opendocs.png" width="63" height="76" border="0"></a> <br> <div class="symbol">Your OpenSource Publisher™</div> </div> </td></tr></table> <div align="center" class="author"> <a href="../products.lxp">Products</a> | <a href="../wheretobuy.lxp">Where to buy</a> | <a href="../bookstore.lxp">Retailers</a> | <a href="../faq.lxp">FAQ</a> | <a href="../writeforus.lxp">Write for Us.</a> | <a href="#contact">Contact Us.</a> </div> <table border="0" cellspacing="3" cellpadding="0" width="100%"><tr><td width="100%"> <div class="content"> <table border="0" cellspacing="2" cellpadding="0" width="100%"><tr><td width="100%"> <div align="center"><H4 CLASS="AUTHOR"><A NAME="AEN5">Boudewijn Rempt</A><br><a href="../../https@secure.linuxports.com/opendocs/default.htm"><img src=odpyqt125.png></a><br>ISBN: 0-97003300-4-4<br><a href="../../https@secure.linuxports.com/opendocs/default.htm">Available from bookstores everywhere or you can order it here.</a><p>You can download the source files for the book <a href="pyqtsrc.tgz">(code / eps) here.</a><hr></div> <HTML><HEAD><TITLE>Testing signals and slots</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.72"><LINKREL="HOME"TITLE="GUI Programming with Python: QT Edition"HREF="book1.htm"><LINKREL="UP"TITLE="Automatic testing with PyUnit"HREF="c5064.htm"><LINKREL="PREVIOUS"TITLE="Large projects"HREF="x5234.htm"><LINKREL="NEXT"TITLE="Conclusion"HREF="x5285.htm"></HEAD><BODYCLASS="SECT1"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#0000FF"VLINK="#840084"ALINK="#0000FF"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">GUI Programming with Python: QT Edition</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><A accesskey="P" href="index.lxp@lxpwrap=x5234_252ehtm.htm">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">Chapter 14. Automatic testing with PyUnit</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><A accesskey="N" href="index.lxp@lxpwrap=x5285_252ehtm.htm">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1">Testing signals and slots</A></H1><P>It's quite difficult to work the signals and slots mechanism into the unittest framework. This is not surprising, since signals and slots quintessentially join components together, and the unittests are meant to test each component separately.</P><P>However, you might want to test whether calling a method on a certain object causes it to emit the right signals. We need a bit of a custom framework for that purpose, a kind of signal test.</P><P>You can use the <TTCLASS="CLASSNAME">ConnectionBox</TT> from the following script for that purpose. It is a simple class, derived from <TTCLASS="CLASSNAME">QObject</TT>, which has one slot, <TTCLASS="FUNCTION">slotSlot()</TT>, that can be connected to a signal with any number of arguments.</P><P>The arguments to the signal are stored in the <TTCLASS="CLASSNAME">ConnectionBox</TT>, so they can be checked later using the various assertion functions.</P><P>I have provided three assertion functions, one to check whether the signal did arrive (<TTCLASS="FUNCTION">assertSignalArrived</TT>), one to check whether the number of arguments was right, (<TTCLASS="FUNCTION">assertNumberOfArguments</TT>), and one to check the types of the arguments using the Python <TTCLASS="FILENAME">types</TT> (<TTCLASS="FUNCTION">assertArgumentTypes</TT>). This provides typenames for all built-in types, but objects created from all user-defined classes (including PyQt classes), belong to the <TTCLASS="VARNAME">InstanceType</TT>. This means that you cannot check whether you got a <TTCLASS="CLASSNAME">QListViewItem</TT> or a <TTCLASS="CLASSNAME">QListView</TT> from a PyQt signal using this function.</P><P>It would be a nice exercise to extend this assert with checking objects using the <TTCLASS="CLASSNAME">QObject</TT>.<TTCLASS="FUNCTION">className()</TT> method. Feel free...</P><PRECLASS="PROGRAMLISTING">## signals.py - unit-testing signals#import sysimport unittestimport typesfrom docviewdoc import DocviewDocfrom qt import *class ConnectionBox(QObject): def __init__(self, *args): apply(QObject.__init__,(self,)+args) self.signalArrived=0 self.args=[] def slotSlot(self, *args): self.signalArrived=1 self.args=args def assertSignalArrived(self, signal=None): if not self.signalArrived: raise AssertionError, ("signal %s did not arrive" % signal) def assertNumberOfArguments(self, number): if number <> len(self.args): raise AssertionError, \ ("Signal generated %i arguments, but %i were expected" % (len(self.args), number)) def assertArgumentTypes(self, *args): if len(args) <> len(self.args): raise AssertionError, \ ("Signal generated %i arguments, but %i were given to this function" % (len(self.args), len(args))) for i in range(len(args)): if type(self.args[i]) != args[i]: raise AssertionError, \ ( "Arguments don't match: %s received, should be %s." % (type(self.args[i]), args[i]))class SignalsTestCase(unittest.TestCase): """This testcase tests the testing of signals """ def setUp(self): self.doc=DocviewDoc() self.connectionBox=ConnectionBox() def tearaDown(self): self.doc.disConnect() self.doc=None self.connectionBox=None def checkSignalDoesArrive(self): """Check whether the sigDocModified signal arrives""" self.connectionBox.connect(self.doc, PYSIGNAL("sigDocModified"), self.connectionBox.slotSlot) self.doc.slotModify() self.connectionBox.assertSignalArrived("sigDocModified") def checkSignalDoesNotArrive(self): """Check whether the sigDocModifiedXXX signal does not arrive""" self.connectionBox.connect(self.doc, PYSIGNAL("sigDocModifiedXXX"), self.connectionBox.slotSlot) self.doc.slotModify() try: self.connectionBox.assertSignalArrived("sigDocModifiedXXX") except AssertionError: pass else: fail("The signal _did_ arrive") def checkArgumentToSignal(self): """Check whether the sigDocModified signal has the right number of arguments """ self.connectionBox.connect(self.doc, PYSIGNAL("sigDocModified"), self.connectionBox.slotSlot) self.doc.slotModify() self.connectionBox.assertNumberOfArguments(1) def checkArgumentTypes(self): """Check whether the sigDocModified signal has the right type of arguments. """ self.connectionBox.connect(self.doc, PYSIGNAL("sigDocModified"), self.connectionBox.slotSlot) self.doc.slotModify() self.connectionBox.assertArgumentTypes(types.IntType)def suite(): testSuite=unittest.makeSuite(SignalsTestCase, "check") return testSuitedef main(): runner = unittest.TextTestRunner() runner.run(suite())if __name__=="__main__": main() </PRE><P>Using this <TTCLASS="CLASSNAME">ConnectionBox</TT>, you can test your signals:</P><PRECLASS="SCREEN">boud@calcifer:~/doc/pyqt/ch9 > python signals.pyCheck whether the sigDocModified signal has the right number arguments ... okCheck whether the sigDocModified signal has the right type of arguments ... okCheck whether the sigDocModified signal arrives ... okCheck whether the sigDocModifiedXXX signal does not arrive ... ok------------------------------------------------------------------------------Ran 4 tests in 0.003sOK </PRE></DIV><DIVCLASS="NAVFOOTER"><HRALIGN="LEFT"WIDTH="100%"><TABLESUMMARY="Footer navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top"><A accesskey="P" href="index.lxp@lxpwrap=x5234_252ehtm.htm">Prev</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><A accesskey="H" href="index.lxp@lxpwrap=book1_252ehtm">Home</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><A accesskey="N" href="index.lxp@lxpwrap=x5285_252ehtm.htm">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">Large projects</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><A accesskey="U" href="index.lxp@lxpwrap=c5064_252ehtm.htm">Up</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Conclusion</TD></TR></TABLE></DIV></BODY></HTML> </td> </tr> </table> </td> </tr> </table>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?