Test a function: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|Tcl}}: improve clarity, add explanatory text)
Line 482: Line 482:


=={{header|Tcl}}==
=={{header|Tcl}}==
Testing with Tcl is just about universally performed with the <tt>tcltest</tt> package, which was originally developed for testing Tcl itself, and which is a standard part of a <tt>[[tclsh]]</tt> installation.

{{libheader|tcltest}}
{{libheader|tcltest}}
<lang tcl>package require tcltest 2
<lang tcl>package require tcltest 2
source palindrome.tcl; # Assume that this is what loads the implementation of ‘palindrome’

tcltest::test palindrome-1 {check for palindromicity} -body {
tcltest::test palindrome-1 {check for palindromicity} -body {
palindrome abcdedcba
palindrome abcdedcba
Line 493: Line 497:
palindrome
palindrome
} -returnCodes error -result "wrong # args: should be \"palindrome s\""
} -returnCodes error -result "wrong # args: should be \"palindrome s\""

tcltest::cleanupTests</lang>
tcltest::cleanupTests</lang>
If placed in a file called <tt>palindrome.test</tt>, the following output is produced when it is executed:
<pre>palindrome.test: Total 3 Passed 3 Skipped 0 Failed 0</pre>
Note that only a small fraction of the features of the testing framework are demonstrated here. In particular, it does not show off management of conditional execution, the application of setup and cleanup code, and how these things are assembled into a whole test suite for a large system.

Revision as of 18:28, 21 November 2009

Task
Test a function
You are encouraged to solve this task according to the task description, using any language you may know.

Using a well known testing specific library/module/suite for your language, write some tests for your language's entry in Palindrome. If your language does not have a testing specific library well known to the language's community then state this or omit the language.

AutoHotkey

there is no "well known" testing library, but here is a simple testing framework:
test library: assert.ahk <lang AutoHotkey>

assert.ahk
assert(a, b, test=2)

assert(a, b="blank", test=0) {

 if (b = "blank")

{

   if !a
     msgbox % "blank value"
     return 0

}

   if equal_list(a, b, "`n")
     return 0
   else
   msgbox % test . ":`n" . a . "`nexpected:`n" . b

}

!r::reload

equal_list(a, b, delimiter)

equal_list(a, b, delimiter) {

 loop, parse, b, %delimiter%
 {
   if instr(a, A_LoopField)
     continue
   else
     return 0
 }
 loop, parse, a, %delimiter%
 {
   if instr(b, A_LoopField)
     continue
   else
     return 0
 }
 return 1

} </lang> test example: <lang AutoHotkey> assert(isPalindrome("in girum imus nocte et consumimur igni"), 1 , "palindrome test") assert(broken("in girum imus nocte et consumimur igni"), "works" , "broken test") /* output:


testPalindrome.ahk


broken test: broken expected: works

  • /

broken(x){ return "broken" }

  1. Include assert.ahk
  2. Include palindrome.ahk

</lang>

D

<lang d> unittest {

 assert(isPalindrome("racecar"));
 assert(isPalindrome("bob"));
 assert(!isPalindrome("alice"));

} </lang>

E

Translation of: Python

The standard testing tool in E is Updoc, a system which takes test scripts formatted in the same style as a REPL session and verifies that executing them produces the specified result values.

<lang e>#!/usr/bin/env rune

? def isPalindrome(string :String) { > def upper := string.toUpperCase() > def last := upper.size() - 1 > for i => c ? (upper[last - i] != c) in upper(0, upper.size() // 2) { > return false > } > return true > }

? isPalindrome("")

  1. value: true

? isPalindrome("a")

  1. value: true

? isPalindrome("aa")

  1. value: true

? isPalindrome("baa")

  1. value: false

? isPalindrome("baab")

  1. value: true

? isPalindrome("ba_ab")

  1. value: true

? isPalindrome("ba_ ab")

  1. value: false

? isPalindrome("ba _ ab")

  1. value: true

? isPalindrome("ab"*2)

  1. value: false

? def x := "ab" * 2**15; null

? x.size()

  1. value: 65536

? def xreversed := "ba" * 2**15; null

? isPalindrome(x + xreversed)

  1. value: true

? (x + xreversed).size()

  1. value: 131072</lang>

F#

Library: NUnit
#light
let palindrome (s : string) =
    let r = new string(s.ToUpper().ToCharArray() |> Array.rev)
    r = s.ToUpper()
    
#r @"nunit\nunit.framework.dll" // add reference to the NUnit framework
open NUnit.Framework
[<TestFixture>]
type TestCases = class
    new() = {}
    [<Test>]
    member x.Test01() =
        Assert.IsTrue(palindrome "radar")
    
    [<Test>]
    member x.Test02() =
        Assert.IsFalse(palindrome "hello")
end

Haskell

A notable testing library for Haskell is QuickCheck. It works in a way particularly supported by Haskell's type inference: you provide a function return a boolean, the test, and QuickCheck automatically generates random values for the function's parameters and checks that it returns True for all of them.

<lang haskell>import Test.QuickCheck

isPalindrome :: String -> Bool isPalindrome x = x == reverse x

{- There is no built-in definition of how to generate random characters;

  here we just specify ASCII characters. Generating strings then automatically
  follows from the definition of String as list of Char. -}

instance Arbitrary Char where

 arbitrary = choose ('\32', '\127')

-- /------------------------- the randomly-generated parameters -- | /------------------ the constraint on the test values -- | | /- the condition which should be true -- v v v main = do

 putStr "Even palindromes: " >> quickCheck (\s   ->                  isPalindrome (s ++ reverse s))
 putStr "Odd palindromes:  " >> quickCheck (\s   -> not (null s) ==> isPalindrome (s ++ (tail.reverse) s))
 putStr "Non-palindromes:  " >> quickCheck (\i s -> not (null s) && 0 <= i && i < length s && i*2 /= length s
                                                                 ==> not (isPalindrome (take i s ++ "•" ++ drop i s)))</lang>

The ==> operator is used to constrain the randomly-generated values: the second test needs a nonempty string, and the third needs an index into the string that is not the exact middle.

J

Using the general/unittest Addon to test the isPalin0 verb from Palindrome.

Tests are contained in a test script c:\mypath\palindrome_test.ijs with the following contents: <lang j> NB. Contents of palindrome_test.ijs

NB. Basic testing test_palinA=: monad define

 assert isPalin0 'abcba'
 assert isPalin0 'aa'
 assert isPalin0 
 assert -. isPalin0 'ab'
 assert -. isPalin0 'abcdba'

)

NB. Can test for expected failure instead palinB_expect=: 'assertion failure' test_palinB=: monad define

 assert isPalin0 'ab'

) </lang>

Example Usage: <lang j>

  require 'general/unittest'
  unittest 'c:\mypath\palindrome_test.ijs'

Test: c:\mypath\palindrome_test.ijs palinA .................................. OK palinB .................................. OK </lang>

Java

Works with: Java version 5


Library: JUnit

<lang java5>import static ExampleClass.pali; // or from wherever it is defined import static ExampleClass.rPali; // or from wherever it is defined import org.junit.*; public class PalindromeTest extends junit.framework.TestCase {

   @Before
   public void setUp(){
       //runs before each test
       //set up instance variables, network connections, etc. needed for all tests
   }
   @After
   public void tearDown(){
       //runs after each test
       //clean up instance variables (close files, network connections, etc.).
   }
   /**
    * Test the pali(...) method.
    */
   @Test
   public void testNonrecursivePali() throws Exception {
       assertTrue(pali("abcba"));
       assertTrue(pali("aa"));
       assertTrue(pali("a"));
       assertTrue(pali(""));
       assertFalse(pali("ab"));
       assertFalse(pali("abcdba"));
   }
   /**
    * Test the rPali(...) method.
    */
   @Test
   public void testRecursivePali() throws Exception {
       assertTrue(rPali("abcba"));
       assertTrue(rPali("aa"));
       assertTrue(rPali("a"));
       assertTrue(rPali(""));
       assertFalse(rPali("ab"));
       assertFalse(rPali("abcdba"));
   }
   /**
    * Expect a WhateverExcpetion
    */
   @Test(expected=WhateverException.class)
   public void except(){
       //some code that should throw a WhateverException
   }

}</lang> Most IDEs that support Java will have JUnit built in or will have an easy-to-use plugin for it. For those that don't use these IDEs, test classes can be run from a normal main method and their results will print to standard output: <lang java5>public class RunTests{

 public static main(String[] args){
   org.junit.runner.JUnitCore.runClasses(PalindromeTest.class/*, other classes here if you have more*/);
 }

}</lang>

OCaml

Using the library OUnit.

The module Palindrome is where are compiled the two functions is_palindrome and rem_space from this page. We put these two functions in a file named palindrome.ml and compile it with ocamlc -c palindrome.ml -o palindrome.cmo, then with the code below in the file palindrome_tests.ml we execute the tests with this command line:

ocaml unix.cma -I +oUnit oUnit.cma  palindrome.cmo  palindrome_tests.ml

<lang ocaml>open OUnit open Palindrome

let test_palindrome_1 _ =

 assert_equal true (is_palindrome "aba")

let test_palindrome_2 _ =

 assert_equal true (is_palindrome "abba")

let test_palindrome_3 _ =

 assert_equal true (is_palindrome "abacidAdicaba")

let test_palindrome_4 _ =

 assert_equal false (is_palindrome "xREty5kgPMO")

let test_palindrome_5 _ =

 assert_equal true (is_palindrome(rem_space "in girum imus nocte et consumimur igni"))


let suite = "Test Palindrome" >::: ["test_palindrome_1" >:: test_palindrome_1;

                                   "test_palindrome_2" >:: test_palindrome_2;
                                   "test_palindrome_3" >:: test_palindrome_3;
                                   "test_palindrome_4" >:: test_palindrome_4;
                                   "test_palindrome_5" >:: test_palindrome_5]

let _ =

 run_test_tt_main suite</lang>

Python

This uses the doctest module from the Python standard library. This allows copies of tests run in an interactive session to be re-used as tests.

<lang python>def is_palindrome(s):

   
       >>> is_palindrome()
       True
       >>> is_palindrome('a')
       True
       >>> is_palindrome('aa')
       True
       >>> is_palindrome('baa')
       False
       >>> is_palindrome('baab')
       True
       >>> is_palindrome('ba_ab')
       True
       >>> is_palindrome('ba_ ab')
       False
       >>> is_palindrome('ba _ ab')
       True
       >>> is_palindrome('ab'*2)
       False
       >>> x = 'ab' *2**15
       >>> len(x)
       65536
       >>> xreversed = x[::-1]
       >>> is_palindrome(x+xreversed)
       True
       >>> len(x+xreversed)
       131072
       >>> 
   
   return s == s[::-1]

def _test():

   import doctest
   doctest.testmod()
   #doctest.testmod(verbose=True)

if __name__ == "__main__":

   _test() </lang>

When run in the form as shown above there is no output as all tests pass. If the alternative doctest.testmod line is used with verbose=True, then the following output is produced:

Trying:
    is_palindrome('')
Expecting:
    True
ok
Trying:
    is_palindrome('a')
Expecting:
    True
ok
Trying:
    is_palindrome('aa')
Expecting:
    True
ok
Trying:
    is_palindrome('baa')
Expecting:
    False
ok
Trying:
    is_palindrome('baab')
Expecting:
    True
ok
Trying:
    is_palindrome('ba_ab')
Expecting:
    True
ok
Trying:
    is_palindrome('ba_ ab')
Expecting:
    False
ok
Trying:
    is_palindrome('ba _ ab')
Expecting:
    True
ok
Trying:
    is_palindrome('ab'*2)
Expecting:
    False
ok
Trying:
    x = 'ab' *2**15
Expecting nothing
ok
Trying:
    len(x)
Expecting:
    65536
ok
Trying:
    xreversed = x[::-1]
Expecting nothing
ok
Trying:
    is_palindrome(x+xreversed)
Expecting:
    True
ok
Trying:
    len(x+xreversed)
Expecting:
    131072
ok
2 items had no tests:
    __main__
    __main__._test
1 items passed all tests:
  14 tests in __main__.is_palindrome
14 tests in 3 items.
14 passed and 0 failed.
Test passed.

R

Library: RUnit

See also the functions defineTestSuite and runTestSuite. <lang r> checkTrue(palindroc("aba")) # TRUE checkTrue(!palindroc("ab")) # TRUE checkException(palindroc()) # TRUE checkTrue(palindroc("")) # Error. Uh-oh, there's a bug in the function </lang>

Ruby

Library: test/unit.rb

Using the Ruby unit testing package, all you have to do is to create a subclass of Test::Unit::Testcase that contains methods that begin with "test_". The package will create a test suite and run it for you. <lang ruby>def palindrome?(s)

 s == s.reverse

end

require 'test/unit' class MyTests < Test::Unit::TestCase

 def test_palindrome_ok
   assert(palindrome? "aba")
 end
 def test_palindrome_nok
   assert_equal(false, palindrome?("ab"))
 end
 def test_object_without_reverse
   assert_raise(NoMethodError) {palindrome? 42}
 end
 def test_wrong_number_args
   assert_raise(ArgumentError) {palindrome? "a", "b"}
 end
 def test_show_failing_test
   assert(palindrome?("ab"), "this test case fails on purpose")
 end

end</lang>

$ ruby palindrome.rb
Loaded suite palindrome
Started
...F.
Finished in 0.018 seconds.

  1) Failure:
test_show_failing_test(MyTests) [palindrome.rb:24]:
this test case fails on purpose.
<false> is not true.

5 tests, 5 assertions, 1 failures, 0 errors

Tcl

Testing with Tcl is just about universally performed with the tcltest package, which was originally developed for testing Tcl itself, and which is a standard part of a tclsh installation.

Library: tcltest

<lang tcl>package require tcltest 2 source palindrome.tcl; # Assume that this is what loads the implementation of ‘palindrome’

tcltest::test palindrome-1 {check for palindromicity} -body {

   palindrome abcdedcba

} -result 1 tcltest::test palindrome-2 {check for non-palindromicity} -body {

   palindrome abcdef

} -result 0 tcltest::test palindrome-3 {check for palindrome error} -body {

   palindrome

} -returnCodes error -result "wrong # args: should be \"palindrome s\""

tcltest::cleanupTests</lang> If placed in a file called palindrome.test, the following output is produced when it is executed:

palindrome.test:	Total	3	Passed	3	Skipped	0	Failed	0

Note that only a small fraction of the features of the testing framework are demonstrated here. In particular, it does not show off management of conditional execution, the application of setup and cleanup code, and how these things are assembled into a whole test suite for a large system.