<html>
  <head>
    <meta content="text/html; charset=windows-1252"
      http-equiv="Content-Type">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    Hi Markus,<br>
    <br>
    lucky you, I wish I have time for side projects!<br>
    <br>
    I've been working on cctbx (and writing tests!) for the past 12
    years and can't name any problem using "libtbx testing world". Most
    tests are written this way. Why I am not so keen to use an
    alternative?<br>
    �� - why introduce inconsistency for no obvious clear pressing
    reasons;<br>
    �� - I have no spare time to learn and get used to an alternative
    framework (again, for no obvious clear pressing reason);<br>
    �� - some rare developers (mostly postdocs that come and go) used
    Python test framework in the past on the code that I work too and
    that I have to maintain when people are gone. I find it is an
    irritating overhead for me dealing with these tests, so typically I
    bother to re-write them to use libtbx tools.<br>
    <br>
    All the best,<br>
    Pavel<br>
    <br>
    <br>
    <div class="moz-cite-prefix">On 5/15/15 8:00 AM,
      <a class="moz-txt-link-abbreviated" href="mailto:markus.gerstel@diamond.ac.uk">markus.gerstel@diamond.ac.uk</a> wrote:<br>
    </div>
    <blockquote
cite="mid:415F7F573406BB498256C68158D45674536CF0@EXCHMBX01.fed.cclrc.ac.uk"
      type="cite">
      <meta http-equiv="Content-Type" content="text/html;
        charset=windows-1252">
      <meta name="Generator" content="Microsoft Word 14 (filtered
        medium)">
      <style><!--
/* Font Definitions */
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";
        mso-fareast-language:EN-US;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
span.EmailStyle17
        {mso-style-type:personal-compose;
        font-family:"Calibri","sans-serif";
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri","sans-serif";
        mso-fareast-language:EN-US;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
      <div class="WordSection1">
        <p class="MsoNormal">Dear cctbx developers and users,<o:p></o:p></p>
        <p class="MsoNormal"><o:p>�</o:p></p>
        <p class="MsoNormal">For a side-project of mine I experimented
          with native python unit tests (some information available on
          <a moz-do-not-send="true"
            href="https://docs.python.org/2/library/unittest.html">https://docs.python.org/2/library/unittest.html</a>
          if you are not familiar with it).<o:p></o:p></p>
        <p class="MsoNormal">The python unittest framework has a couple
          of advantages over the libtbx testing world. I found that the
          two most immediate advantages are:<o:p></o:p></p>
        <p class="MsoNormal"><o:p>�</o:p></p>
        <p class="MsoNormal"><i>Automated test discovery.<o:p></o:p></i></p>
        <p class="MsoNormal">There is no need to keep a complete list of
          test files in another python file, which is what we currently
          do in run_tests.py.<o:p></o:p></p>
        <p class="MsoNormal"><o:p>�</o:p></p>
        <p class="MsoNormal"><i>Multiple test functions per python test
            file.<o:p></o:p></i></p>
        <p class="MsoNormal">At the moment we can run multiple tests via
          command line parameters to the python test files. This of
          course means that you need to keep a list of �(test file,
          parameter)� tuples in run_tests.py, and you need some
          boilerplate dispatcher in your test file. This can lead to two
          situations: you may have a number of tests with numeric
          parameters, and no one knows what the parameters stand for.
          One example of this can be found in DIALS, where tst_index.py
          is run with numeric parameters 1 to 4 and 7 to 15, but not 5
          and 6. The alternative situation is that you end up with a
          massive test file, that tests the entire class under test, but
          figuring out what specifically went wrong is probably more
          time consuming than necessary.<o:p></o:p></p>
        <p class="MsoNormal">In contrast in Python unittests any
          function in the file that is named test_* will be identified
          and run as a separate test. I find that this automatically
          leads to smaller and thus more readable tests.<o:p></o:p></p>
        <p class="MsoNormal"><o:p>�</o:p></p>
        <p class="MsoNormal">I understand that libtbx has been developed
          before Python unittest was around, that there is a substantial
          amount of code around that relies on current libtbx behaviour,
          and that there is no pressing need to change anything.<o:p></o:p></p>
        <p class="MsoNormal">However I would like to be able to take
          advantage of the tools that are out there, so I wrote a
          function that uses Python unittest for test discovery, and can
          be placed in run_tests.py. With this function you can then use
          regular Python unittests and run them with either through
          libtbx, with the python unittest tools, or directly. In each
          case you end up with the test results reported in the way you
          would expect.<o:p></o:p></p>
        <p class="MsoNormal"><o:p>�</o:p></p>
        <p class="MsoNormal">What I would like to do is integrate this
          logic in libtbx directly, so that we can use it for all cctbx
          modules. Since it does not modify libtbx default behaviour and
          only becomes active after a change in the run_tests.py of the
          relevant module it should be fully backwards compatible with
          virtually no downsides. What do you think?<o:p></o:p></p>
        <p class="MsoNormal"><o:p>�</o:p></p>
        <p class="MsoNormal">-Markus<o:p></o:p></p>
        <p class="MsoNormal"><o:p>�</o:p></p>
        <p class="MsoNormal"><o:p>�</o:p></p>
        <div
          style="mso-element:para-border-div;border:none;border-bottom:solid
          windowtext 1.0pt;padding:0cm 0cm 1.0pt 0cm">
          <p class="MsoNormal" style="border:none;padding:0cm"><o:p>�</o:p></p>
        </div>
        <p class="MsoNormal"><o:p>�</o:p></p>
        <p class="MsoNormal"><b>run_tests.py previously:<o:p></o:p></b></p>
        <p class="MsoNormal"><i>(..)<o:p></o:p></i></p>
        <p class="MsoNormal">tst_list = (<o:p></o:p></p>
        <p class="MsoNormal">�
          "$D/test/algorithms/profile_model/nave/tst_model.py",<o:p></o:p></p>
        <p class="MsoNormal">)<o:p></o:p></p>
        <p class="MsoNormal"><i>(..)<o:p></o:p></i></p>
        <p class="MsoNormal"><o:p>�</o:p></p>
        <p class="MsoNormal"><b>run_tests.py new:<o:p></o:p></b></p>
        <p class="MsoNormal"><i>(..)<o:p></o:p></i></p>
        <p class="MsoNormal">tst_list = (<o:p></o:p></p>
        <p class="MsoNormal">�
          "$D/test/algorithms/profile_model/nave/tst_model.py",<o:p></o:p></p>
        <p class="MsoNormal">) + discover_unittests("dlstbx")<o:p></o:p></p>
        <p class="MsoNormal"><i>(..)<o:p></o:p></i></p>
        <p class="MsoNormal"><o:p>�</o:p></p>
        <p class="MsoNormal"><b>discover_unittests function:<o:p></o:p></b></p>
        <p class="MsoNormal">def discover_unittests(module,
          pattern='tst_*.py'):<o:p></o:p></p>
        <p class="MsoNormal">� try:<o:p></o:p></p>
        <p class="MsoNormal">��� import inspect<o:p></o:p></p>
        <p class="MsoNormal">��� import os<o:p></o:p></p>
        <p class="MsoNormal">��� import sys<o:p></o:p></p>
        <p class="MsoNormal">��� import unittest<o:p></o:p></p>
        <p class="MsoNormal">� except:<o:p></o:p></p>
        <p class="MsoNormal">��� return tuple([])<o:p></o:p></p>
        <p class="MsoNormal"><o:p>�</o:p></p>
        <p class="MsoNormal">� dist_dir = libtbx.env.dist_path(module)<o:p></o:p></p>
        <p class="MsoNormal">� found_tests =
          unittest.defaultTestLoader.discover(dist_dir, pattern=pattern)<o:p></o:p></p>
        <p class="MsoNormal"><o:p>�</o:p></p>
        <p class="MsoNormal">� def recursive_TestSuite_to_list(suite):<o:p></o:p></p>
        <p class="MsoNormal">��� list = []<o:p></o:p></p>
        <p class="MsoNormal">��� for t in suite:<o:p></o:p></p>
        <p class="MsoNormal">����� if isinstance(t, unittest.TestSuite):<o:p></o:p></p>
        <p class="MsoNormal">�������
          list.extend(recursive_TestSuite_to_list(t))<o:p></o:p></p>
        <p class="MsoNormal">����� elif isinstance(t,
          unittest.TestCase):<o:p></o:p></p>
        <p class="MsoNormal">������� module = t.__class__.__module__<o:p></o:p></p>
        <p class="MsoNormal">������� if module == 'unittest.loader':<o:p></o:p></p>
        <p class="MsoNormal">��������� # This indicates a loading error.<o:p></o:p></p>
        <p class="MsoNormal">��������� # Regenerate file name and try to
          run file directly.<o:p></o:p></p>
        <p class="MsoNormal">��������� path =
          t._testMethodName.replace('.', os.path.sep)<o:p></o:p></p>
        <p class="MsoNormal">��������� list.append("$D/%s.py" % path)<o:p></o:p></p>
        <p class="MsoNormal">������� else:<o:p></o:p></p>
        <p class="MsoNormal">��������� module =
          inspect.getsourcefile(sys.modules[module])<o:p></o:p></p>
        <p class="MsoNormal">��������� function = "%s.%s" %
          (t.__class__.__name__, t._testMethodName)<o:p></o:p></p>
        <p class="MsoNormal">��������� list.append([module, function])<o:p></o:p></p>
        <p class="MsoNormal">����� else:<o:p></o:p></p>
        <p class="MsoNormal">������� raise Exception("Unknown test
          object (%s)" % t)<o:p></o:p></p>
        <p class="MsoNormal">��� return list<o:p></o:p></p>
        <p class="MsoNormal">� test_list =
          recursive_TestSuite_to_list(found_tests)<o:p></o:p></p>
        <p class="MsoNormal">� return tuple(test_list)<o:p></o:p></p>
        <p class="MsoNormal"><o:p>�</o:p></p>
      </div>
      <p align="justify">�</p>
      <p align="justify">--�</p>
      <p align="justify">This e-mail and any attachments may contain
        confidential, copyright and or privileged material, and are for
        the use of the intended addressee only. If you are not the
        intended addressee or an authorised recipient of the addressee
        please notify us of receipt by returning the e-mail and do not
        use, copy, retain, distribute or disclose the information in or
        attached to the e-mail.<br>
        Any opinions expressed within this e-mail are those of the
        individual and not necessarily of Diamond Light Source Ltd. <br>
        Diamond Light Source Ltd. cannot guarantee that this e-mail or
        any attachments are free from viruses and we cannot accept
        liability for any damage which you may sustain as a result of
        software viruses which may be transmitted in or with the
        message.<br>
        Diamond Light Source Limited (company no. 4375679). Registered
        in England and Wales with its registered office at Diamond
        House, Harwell Science and Innovation Campus, Didcot,
        Oxfordshire, OX11 0DE, United Kingdom<br>
        �</p>
      <br>
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <br>
      <pre wrap="">_______________________________________________
cctbxbb mailing list
<a class="moz-txt-link-abbreviated" href="mailto:cctbxbb@phenix-online.org">cctbxbb@phenix-online.org</a>
<a class="moz-txt-link-freetext" href="http://phenix-online.org/mailman/listinfo/cctbxbb">http://phenix-online.org/mailman/listinfo/cctbxbb</a>
</pre>
    </blockquote>
    <br>
  </body>
</html>