Monthly Archives: July 2014

Python testing framework for codingbat tutorial

Working through the codingbat.com Python tutorial, I created this testing framework for problems that return a value (do they all??). This demonstrates using it with a problem that returns a boolean:

### DO NOT EDIT...start

### Global variables
totalCount = 0    #: The total number of tests attempted
successCount = 0  #: The number of tests having the exepected response

def printIfExpectedNotActual(expected, actual, param_debugging):
    """
        If the expected and actual responses are equal, this prints
        nothing. Otherwise this prints the expected value, plus the
        names and values of all parameters.

        This also increments the number of total tests and successful
        tests (when expected equals actual), as stored in the global
        variables ``successCount`` and ``totalCount``.

        expected
            The value that should be returned by the function.
        actual
            The value actually returned by the function.
        param_debugging
            A string of all parameter names and values, in the format
            ``"name1=" + value1 + ", name2=" + value2 + ...``. When the
            expected and actual values are equal, this is ignored.
    """
    global totalCount; totalCount+=1
    if(actual == expected):
        global successCount; successCount+=1
        return
    print("FAILURE: expected='", expected, "', actual='", actual, "', ",\
        param_debugging, sep="")

### DO NOT EDIT...end

"""
    EDIT THIS: Middleman between unit assertion and the primary function.
"""
            #EDIT LINE: The parameters after
            #      expected
def testExpectedWithParams(expected, n):

            #EDIT LINE: actual = [THE FUNCTION CALL]
    actual = pos_neg(n)

            #EDIT LINE: each parameter: "x=" + str(x) + ", y=" + y ...
    paramDebugging = "n=" + str(n)

            #DO NOT edit next line:
    printIfExpectedNotActual(expected, actual, paramDebugging)


"""
    EDIT THIS: The function to test
               This is what you paste into codingbat!
"""
def near_hundred(n):
    return  ((abs(100 - n) <= 10)  or  (abs(200 - n) <= 10))

"""
    EDIT THIS: Test calls
"""
testExpectedWithParams(False, 89)
for i in range(90, 111):
    testExpectedWithParams(True, i)
testExpectedWithParams(False, 111)
testExpectedWithParams(False, 189)
for i in range(190, 211):
    testExpectedWithParams(True, i)
testExpectedWithParams(False, 211)

"""
#Examples from codingbat:
#Copied directly from coding bat:
near_hundred(93) ? True
near_hundred(90) ? True
near_hundred(89) ? False
"""

#Examples from codingbat:
#Function name changed to testExpectedWithParams, expected value as
#1st param
testExpectedWithParams(True, 93)
testExpectedWithParams(True, 90)
testExpectedWithParams(False, 89)

#Extra tests:

### DO NOT EDIT the next line
print("total tests=", totalCount, ", correct=", successCount, \
    ", incorrect=", (totalCount - successCount), sep="")

Success response:

total tests=49, correct=49, incorrect=0

Example failure response, after changing

  • testExpectedWithParams(True, 90) to testExpectedWithParams(False, 90), and
  • testExpectedWithParams(False, 89) to testExpectedWithParams(True, 89)

FAILURE: expected='False', actual='True', n=90
FAILURE: expected='True', actual='False', n=89
total tests=49, correct=47, incorrect=2


And another demonstrating a problem that returns a string:

"""
    EDIT THIS: Middleman between unit assertion and the primary function.
"""
            #EDIT LINE: The parameters after
            #      expected
def testExpectedWithParams(expected, str2, n):

            #EDIT LINE: actual = [THE FUNCTION CALL]
    actual = not_string(str2, n)

            #EDIT LINE: each parameter: "x=" + str(x) + ", y=" + str(y) ...
    paramDebugging = "str2=" + str(str2) + ", n=" + str(n)

            #Do not edit next line:
    printIfExpectedNotActual(expected, actual, paramDebugging)

"""
    EDIT THIS: The function to test
               This is what you paste into codingbat!
"""
def not_string(str2, n):  #Actually named "str", which masks the built-in "str"
    return  str2[0:n] + str2[(n + 1):len(str2)]

"""
    EDIT THIS: Test calls
"""
testExpectedWithParams('itten', 'kitten', 0)
testExpectedWithParams('ktten', 'kitten', 1)
testExpectedWithParams('kiten', 'kitten', 2)
testExpectedWithParams('kiten', 'kitten', 3)
testExpectedWithParams('kittn', 'kitten', 4)
testExpectedWithParams('kitte', 'kitten', 5)

#Examples from codingbat:
testExpectedWithParams('ktten', 'kitten', 1)  #missing_char('kitten', 1) ? 'ktten'
testExpectedWithParams('itten', 'kitten', 0)  #missing_char('kitten', 0) ? 'itten'
testExpectedWithParams('kittn', 'kitten', 4)  #missing_char('kitten', 4) ? 'kittn'

Success response:

total tests=9, correct=9, incorrect=0

Advertisements

Introducing “Codelet”: Automated insertion of example code into JavaDoc

Codelet (GitHub link) automates the insertion of already unit-tested example code into your JavaDoc, using taglets. As with all taglets, Codelet is executed as part of javadoc.exe. It is now released in beta.

There are four Codelet taglets:

{@codelet.and.out}: Displays source code immediately followed by its output
{@codelet}: Displays source code only
{@codelet.out}: Displays output only
{@file.textlet}: Displays the contents of any plain-text file, such as the input for an example code.

A common example:

  {@.codelet.and.out com.github.aliteralmind.codelet.examples.adder.AdderDemo%eliminateCommentBlocksAndPackageDecl()}

which uses the eliminateCommentBlocksAndPackageDecl() “customizer” to eliminate the package declaration line and all multi-line comments (such as the license and JavaDoc blocks).

Output (between the horizontal rules):


Source

public class AdderDemo  {
   public static final void main(String[] ignored)  {

      Adder adder = new Adder();
      System.out.println(adder.getSum());

      adder = new Adder(5, -7, 20, 27);
      System.out.println(adder.getSum());
   }
}

Output:

0
45

If AdderDemo required command line parameters, you’d instead use

  {@.codelet.and.out com.github.aliteralmind.codelet.examples.adder.AdderDemo("command line params", true, 3)%eliminateCommentBlocksAndPackageDecl()}

An alternative is to display only a portion of the example’s code: A code snippet:

  {@.codelet.and.out com.github.aliteralmind.codelet.examples.adder.AdderDemo%lineRange(1, false, "Adder adder", 2, false, "println(adder.getSum())", "^ ")}

This displays the same example as above, starting with (the line containing) Adder adder, and ending with the second println(adder.getSum()). This also eliminates the extra indentation, which in this case is six spaces.

Output (between the horizontal rules):


Source

Adder adder = new Adder();
System.out.println(adder.getSum());

adder = new Adder(5, -7, 20, 27);
System.out.println(adder.getSum());

Output:

0
45

All taglets accept customizers.

It is possible to write your own customizers which, for example, can “linkify” function names, change the template in which source-and-output is displayed, and do any arbitrary alteration to any or all lines. Examples include highlighting something in yellow, or making regular expression replacements.

As a final example, and as a contrast to those above, here is the taglet that blindly prints all lines from an example code, without any changes. It uses no customizer:

  {@.codelet.and.out com.github.aliteralmind.codelet.examples.adder.AdderDemo}

Output (between the horizontal rules):


Source

/*license*\
   Codelet: Copyright (C) 2014, Jeff Epstein (aliteralmind __DASH__ github __AT__ yahoo __DOT__ com)

   This software is dual-licensed under the:
   - Lesser General Public License (LGPL) version 3.0 or, at your option, any later version;
   - Apache Software License (ASL) version 2.0.

   Either license may be applied at your discretion. More information may be found at
   - http://en.wikipedia.org/wiki/Multi-licensing.

   The text of both licenses is available in the root directory of this project, under the names "LICENSE_lgpl-3.0.txt" and "LICENSE_asl-2.0.txt". The latest copies may be downloaded at:
   - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
   - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
\*license*/
package  com.github.aliteralmind.codelet.examples.adder;
/**
   <P>Demonstration of {@code com.github.aliteralmind.codelet.examples.adder.Adder}.</P>

   <P>{@code java com.github.aliteralmind.codelet.examples.AdderDemo}</P>

   @since  0.1.0
   @author  Copyright (C) 2014, Jeff Epstein ({@code aliteralmind __DASH__ github __AT__ yahoo __DOT__ com}), dual-licensed under the LGPL (version 3.0 or later) or the ASL (version 2.0). See source code for details. <A HREF=&quot;http://codelet.aliteralmind.com&quot;>{@code http://codelet.aliteralmind.com}</A>, <A HREF=&quot;https://github.com/aliteralmind/codelet&quot;>{@code https://github.com/aliteralmind/codelet}</A>
 **/
public class AdderDemo  {
   public static final void main(String[] ignored)  {

      Adder adder = new Adder();
      System.out.println(adder.getSum());

      adder = new Adder(5, -7, 20, 27);
      System.out.println(adder.getSum());
   }
}

Output:

0
45

Codelet is now available in beta. Please consider giving it a try, and posting your comments and criticisms in the GitHub issue tracker.