Updating the project-level script to provide coverage reports

Update the project-level script to generate HTML, XML, and console coverage reports as runnable options.

Getting ready

  • Install coverage by typing pip install coverage.
  • Create the network management application as described in the Building a network management application section.

How to do it...

With these steps, we will explore how to use coverage programmatically in a project management script.

  1. Create a new file called recipe58.py to store this command-line script.
  2. Create a script that uses getopt to parse command-line arguments.
    import getopt
    import logging
    import nose
    import os
    import os.path
    import re
    import sys
    from glob import glob
    
    def usage():
        print
        print "Usage: python recipe58.py [command]"
        print
        print "	--help"
        print "	--test"
        print "	--package"
        print "	--publish"
        print "	--register"
        print
    
    try:
        optlist, args = getopt.getopt(sys.argv[1:],
                "h",
               ["help", "test", "package", "publish", "register"])
    except getopt.GetoptError:
        # print help information and exit:
        print "Invalid command found in %s" % sys.argv
        usage()
        sys.exit(2)
  3. Add a test function that uses coverage's API to gather metrics and then generate a console report, an HTML report, and an XML report while also using nose's API to run the tests.
    def test():
        from coverage import coverage
    
        cov = coverage()
        cov.start()
    
        suite = ["recipe52", "recipe52b", "recipe55", "recipe56", "recipe57"]
        print("Running suite %s" % suite)
        args = [""]
        args.extend(suite)
        nose.run(argv=args)
    
        cov.stop()
    
        modules_to_report = [module + ".py" for module in suite]
        modules_to_report.append("network.py")
    
        cov.report(morfs=modules_to_report)
        cov.html_report(morfs=modules_to_report, 
                        directory="recipe58")
        cov.xml_report(morfs=modules_to_report, 
                       outfile="recipe58.xml")
  4. Add some other stubbed out functions to simulate packaging, publishing, and registering this project.
    def package():
        print "This is where we can plug in code to run " + 
              "setup.py to generate a bundle."
    
    def publish():
        print "This is where we can plug in code to upload " + 
              "our tarball to S3 or some other download site."
    
    def register():
        print "setup.py has a built in function to " + 
              "'register' a release to PyPI. It's " + 
              "convenient to put a hook in here."
        # os.system("%s setup.py register" % sys.executable)
  5. Add code that processes the command-line arguments and calls the functions defined earlier.
    if len(optlist) == 0:
        usage()
        sys.exit(1)
    
    # Check for help requests, which cause all other
    # options to be ignored.
    for option in optlist:
        if option[0] in ("--help", "-h"):
            usage()
            sys.exit(1)
    
    
    # Parse the arguments, in order
    for option in optlist:
        if option[0] in ("--test"):
            test()
    
        if option[0] in ("--package"):
            package()
    	
        if option[0] in ("--publish"):
            publish()
    
        if option[0] in ("--register"):
            register()
  6. Run the script using the --test option.
    How to do it...
  7. Open the HTML report using your favorite browser.
    How to do it...
  8. Inspect recipe58.xml.

How it works...

The coverage API is easy to use as shown in the following steps:

  1. In the test method, we create a coverage() instance.
        from coverage import coverage
    
        cov = coverage()
  2. We need to call the start method to begin tracing.
        cov.start()
  3. Next, we need to exercise the main code. In this case, we are using the nose API. We will use it to run the various recipes coded in this chapter.
        suite = ["recipe52", "recipe52b", "recipe55", "recipe56", "recipe57"]
        print("Running suite %s" % suite)
        args = [""]
        args.extend(suite)
        nose.run(argv=args)
  4. Then we need to stop coverage from tracing.
        cov.stop()
  5. Now that we have gathered metrics, we can generate a console report, an HTML report, and an XML report.
        modules_to_report = [module + ".py" for module in suite]
        modules_to_report.append("network.py")
    
        cov.report(morfs=modules_to_report)
        cov.html_report(morfs=modules_to_report, 
                        directory="recipe58")
        cov.xml_report(morfs=modules_to_report, 
                       outfile="recipe58.xml")

The first report is a console report. The second report is an HTML report written into the subdirectory recipe58. The third report is an XML report in Cobertura format written to recipe58.xml.

There's more…

There are many more options to fine tune the gathering as well as reporting. Just visit the online documentation at http://nedbatchelder.com/code/coverage/api.html for more details.

Can we only use getopt?

Python 2.7 introduces argparse as an alternative. Current documentation gives no indication that getopt is deprecated, so it's safe to use as we have just done. The getopt module is a nice, easy-to-use command-line parser.

What's wrong with using the various command-line tools?

There is nothing wrong with using tools like nosetests, the coverage tool, setup.py, and the many other tools that come with the Python libraries. The purpose of this recipe is to offer a convenient, alternative approach that brings all these tools into one central script. By investing a little bit of time in this script, we don't have to remember how to use all these features, but instead can develop our script to support the development workflow of our project.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.36.146