Test a function: Difference between revisions
add minimal Euphoria testing code |
|||
Line 280: | Line 280: | ||
? (x + xreversed).size() |
? (x + xreversed).size() |
||
# value: 131072</lang> |
# value: 131072</lang> |
||
=={{header|Euphoria}}== |
|||
<lang euphoria> |
|||
--unittest in standard library 4.0+ |
|||
include std/unittest.e |
|||
include palendrome.e --routines to be tested |
|||
object p = "12321" |
|||
test_equal("12321", 1, isPalindrome(p)) |
|||
test_equal("r12321", 1, isPalindrome(reverse(p))) |
|||
test_report() |
|||
</lang> |
|||
=={{header|F_Sharp|F#}}== |
=={{header|F_Sharp|F#}}== |
||
Line 299: | Line 317: | ||
member x.Test02() = |
member x.Test02() = |
||
Assert.IsFalse(palindrome "hello")</lang> |
Assert.IsFalse(palindrome "hello")</lang> |
||
=={{header|Factor}}== |
=={{header|Factor}}== |
Revision as of 06:36, 15 February 2012
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
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" }
- Include assert.ahk
- Include palindrome.ahk</lang>
Brat
<lang brat>include :assert
palindrome? = { str |
str = str.downcase.sub /\s+/ "" str == str.reverse
}
setup name: "palindrome test" {
test "is a palindrome" { assert { palindrome? "abba" } }
test "is not a palindrome" { assert_false { palindrome? "abb" } }
test "is not a string" { assert_fail { palindrome? 1001 } }
test "this test fails" { assert { palindrome? "blah blah" } }
}</lang>
Output:
Loading tests... Running palindrome test... (4/4) this test fails Test failure(s): 1. 'this test fails': assert failed 4 tests, 4 assertions, 1 failures.
C
<lang C>#include <assert.h> int IsPalindrome(char *Str);
int main() {
assert(IsPalindrome("racecar")); assert(IsPalindrome("alice"));
} </lang>
Clojure
<lang lisp> (use 'clojure.test)
(deftest test-palindrome?
(is (= true (palindrome? "amanaplanacanalpanama"))) (is (= false (palindrome? "Test 1, 2, 3"))))
(run-tests) </lang>
C#
First, using the VisualStudio TestTools for unit tests. I'm testing both of the methods for palindrome detection created in the article.
<lang Csharp> using Microsoft.VisualStudio.TestTools.UnitTesting; using PalindromeDetector.ConsoleApp;
namespace PalindromeDetector.VisualStudioTests {
[TestClass] public class VSTests { [TestMethod] public void PalindromeDetectorCanUnderstandPalindrome() { //Microsoft.VisualStudio.QualityTools.UnitTestFramework v4.0.30319 bool expected = true; bool actual; actual = Program.IsPalindrome("1"); Assert.AreEqual(expected, actual); actual = Program.IsPalindromeNonRecursive("1"); Assert.AreEqual(expected, actual); actual = Program.IsPalindrome("ingirumimusnocteetconsumimurigni"); Assert.AreEqual(expected, actual); actual = Program.IsPalindromeNonRecursive("ingirumimusnocteetconsumimurigni"); Assert.AreEqual(expected, actual); } [TestMethod] public void PalindromeDetecotryCanUnderstandNonPalindrome() { bool notExpected = true; bool actual = Program.IsPalindrome("ThisIsNotAPalindrome"); Assert.AreNotEqual(notExpected, actual); actual = Program.IsPalindromeNonRecursive("ThisIsNotAPalindrome"); Assert.AreNotEqual(notExpected, actual); } }
}</lang>
Second, NUnit tests. Couldn't test these because of namespace issues with NUnit, but I'm sure they work. <lang Csharp> using NUnit.Framework; using PalindromeDetector.ConsoleApp;
namespace PalindromeDetector.VisualStudioTests {
[TestFixture] public class NunitTests { [Test] public void PalindromeDetectorCanUnderstandPalindrome() { //nunit.framework v2.0.50727 bool expected = true; bool actual; actual = Program.IsPalindrome("1"); Assert.AreEqual(expected, actual); actual = Program.IsPalindromeNonRecursive("1"); Assert.AreEqual(expected, actual); actual = Program.IsPalindrome("ingirumimusnocteetconsumimurigni"); Assert.AreEqual(expected, actual); actual = Program.IsPalindromeNonRecursive("ingirumimusnocteetconsumimurigni"); Assert.AreEqual(expected, actual); } [Test] public void PalindromeDetectorUnderstandsNonPalindrome() { bool notExpected = true; bool actual; actual = Program.IsPalindrome("NotAPalindrome"); Assert.AreEqual(notExpected, actual); actual = Program.IsPalindromeNonRecursive("NotAPalindrome"); Assert.AreEqual(notExpected, actual); } }
}</lang>
D
<lang d>unittest {
assert(isPalindrome("racecar")); assert(isPalindrome("bob")); assert(!isPalindrome("alice"));
}</lang>
Delphi
Using built in assertions.
<lang Delphi> Assert(IsPalindrome('salàlas'), 'salàlas is a valid palindrome');
Assert(IsPalindrome('Ingirumimusnocteetconsumimurigni'), 'Ingirumimusnocteetconsumimurigni is a valid palindrome'); Assert(not IsPalindrome('123'), '123 is not a valid palindrome');</lang>
Using DUnit, an open source unit testing framework that is bundled with Delphi.
<lang Delphi> Check(IsPalindrome('salàlas'), 'salàlas is a valid palindrome');
Check(IsPalindrome('Ingirumimusnocteetconsumimurigni'), 'Ingirumimusnocteetconsumimurigni is a valid palindrome'); Check(not IsPalindrome('123'), '123 is not a valid palindrome');</lang>
E
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("")
- value: true
? isPalindrome("a")
- value: true
? isPalindrome("aa")
- value: true
? isPalindrome("baa")
- value: false
? isPalindrome("baab")
- value: true
? isPalindrome("ba_ab")
- value: true
? isPalindrome("ba_ ab")
- value: false
? isPalindrome("ba _ ab")
- value: true
? isPalindrome("ab"*2)
- value: false
? def x := "ab" * 2**15; null
? x.size()
- value: 65536
? def xreversed := "ba" * 2**15; null
? isPalindrome(x + xreversed)
- value: true
? (x + xreversed).size()
- value: 131072</lang>
Euphoria
<lang euphoria> --unittest in standard library 4.0+ include std/unittest.e include palendrome.e --routines to be tested
object p = "12321"
test_equal("12321", 1, isPalindrome(p)) test_equal("r12321", 1, isPalindrome(reverse(p)))
test_report()
</lang>
F#
<lang fsharp>let palindrome (s : string) =
let a = s.ToUpper().ToCharArray() Array.rev a = a
open NUnit.Framework
[<TestFixture>] type TestCases() =
[<Test>] member x.Test01() = Assert.IsTrue(palindrome "radar") [<Test>] member x.Test02() = Assert.IsFalse(palindrome "hello")</lang>
Factor
By convention, if there is a vocabulary at x/x.factor, then its tests belong in x/x-tests.factor.
palindrome/palindrome.factor
<lang factor>USING: kernel sequences ; IN: palindrome
- palindrome? ( string -- ? ) dup reverse = ;</lang>
palindrome/palindrome-tests.factor
<lang factor>USING: palindrome tools.test ; IN: palindrome.tests
[ t ] [ "racecar" palindrome ] unit-test [ f ] [ "ferrari" palindrome ] unit-test</lang>
To run these tests from the listener:
<lang factor>( scratchpad ) "palindrome" test</lang>
Factor's tutorial, Your first program, uses palindrome? as its example. The tutorial shows how to create tests for palindrome? and how to fix a failing test.
Fantom
To use the built-in test library, the program must be compiled into a pod. The layout for a simple pod and its build file is given in the documentation, and also information for adding and running the test files.
<lang fantom> class TestPalindrome : Test {
public Void testIsPalindrome () { verify(Palindrome.isPalindrome("")) verify(Palindrome.isPalindrome("a")) verify(Palindrome.isPalindrome("aa")) verify(Palindrome.isPalindrome("aba")) verifyFalse(Palindrome.isPalindrome("abb")) verify(Palindrome.isPalindrome("salàlas")) verify(Palindrome.isPalindrome("In girum imus nocte et consumimur igni".lower.replace(" ",""))) }
} </lang>
Go
Using Go's standard command, gotest. <lang go>package pal
import "testing"
func TestPals(t *testing.T) {
pals := []string{ "", ".", "11", "ere", "ingirumimusnocteetconsumimurigni", } for _, s := range pals { if !IsPal(s) { t.Error("IsPal returned false on palindrome,", s) } }
}
func TestNonPals(t *testing.T) {
nps := []string{ "no", "odd", "salàlas", } for _, s := range nps { if IsPal(s) { t.Error("IsPal returned true on non-palindrome,", s) } }
}</lang> Output of gotest:
rm -f _test/pal.a 6g -p pal -o _gotest_.6 pal.go pal_test.go rm -f _test/pal.a gopack grc _test/pal.a _gotest_.6 PASS
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
<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>
Lua
<lang lua>assert( ispalindrome("ABCBA") ) assert( ispalindrome("ABCDE") )</lang>
Mathematica
<lang Mathematica>myFun[x_] := Block[{y},y = x^2; Assert[y > 5]; Sin[y]] On[Assert];myFun[1.0]</lang>
Output:
Assert::asrtf: Assertion y>5 failed. 0.841471
NetRexx
<lang NetRExx>/* NetRexx */
options replace format comments java crossref savelog symbols binary
import junit.framework.TestCase import RCPalindrome
class RCTestAFunction public final extends TestCase
method setUp public
return
method tearDown public
return
method testIsPal public signals AssertionError
assertTrue(RCPalindrome.isPal(Rexx 'abcba')) assertTrue(RCPalindrome.isPal(Rexx 'aa')) assertTrue(RCPalindrome.isPal(Rexx 'a')) assertTrue(RCPalindrome.isPal(Rexx )) assertFalse(RCPalindrome.isPal(Rexx 'ab')) assertFalse(RCPalindrome.isPal(Rexx 'abcdba'))
return
method except signals RuntimeException
signal RuntimeException()
method main(args = String[]) public constant
testResult = org.junit.runner.JUnitCore.runClasses([RCTestAFunction.class]) secs = Rexx testResult.getRunTime / 1000.0
if testResult.wasSuccessful then say 'Tests successful' else say 'Tests failed' say ' failure count:' testResult.getFailureCount say ' ignore count:' testResult.getIgnoreCount say ' run count:' testResult.getRunCount say ' run time:' secs.format(null, 3)
return
</lang>
- Output
Tests successful failure count: 0 ignore count: 0 run count: 1 run time: 0.015
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>
PARI/GP
PARI/GP comes with a testing framework for gp. Testing the palindrome function (if converted with gp2c and added to PARI) would consist of adding lines like
? ispal("abc") 0 ? ispal("aba") 1
Pascal
See Delphi
Perl
A test file, with a .t suffix, is just a Perl program that prints a test stream in Test Anything Protocol (TAP). There are modules to help print things in the correct TAP format; Perl 5 bundles Test, Test::Simple and Test::More.
This example uses Test and requires the Palindrome.pm file from Palindrome detection#Perl.
<lang perl># ptest.t use strict; use warnings;
use Test;
my %tests; BEGIN {
# plan tests before loading Palindrome.pm %tests = ( 'A man, a plan, a canal: Panama.' => 1, 'My dog has fleas' => 0, "Madam, I'm Adam." => 1, '1 on 1' => 0, 'In girum imus nocte et consumimur igni' => 1, => 1, );
# plan 4 tests per string plan tests => (keys(%tests) * 4);
}
use Palindrome;
for my $key (keys %tests) {
$_ = lc $key; # convert to lowercase s/[\W_]//g; # keep only alphanumeric characters
my $expect = $tests{$key}; my $note = ("\"$key\" should " . ($expect ? : 'not ') . "be a palindrome.");
ok palindrome == $expect, 1, "palindrome: $note"; ok palindrome_c == $expect, 1, "palindrome_c: $note"; ok palindrome_r == $expect, 1, "palindrome_r: $note"; ok palindrome_e == $expect, 1, "palindrome_e: $note";
}</lang>
The program produces TAP output.
$ perl ptest.t 1..24 # Running under perl version 5.010001 for openbsd # Current time local: Mon Jan 31 17:44:06 2011 # Current time GMT: Mon Jan 31 22:44:06 2011 # Using Test.pm version 1.25_02 ok 1 ok 2 ok 3 ... ok 24
The first line '1..24' plans for 24 tests, so that one can detect if the script aborted itself before it finished all the tests. A line like 'ok 1' is a passing test, 'not ok 1' is a failing test.
To find those 'not ok' lines, one can run a TAP harness. The "prove" program is a TAP harness that comes with Perl. (By default, "prove" runs all the test files in the "t" subdirectory. I did not make "t", so I will run "prove ptest.t" instead.)
$ prove ptest.t ptest.t .. ok All tests successful. Files=1, Tests=24, 0 wallclock secs ( 0.00 usr 0.02 sys + 0.01 cusr 0.00 csys = 0.03 CPU) Result: PASS
All the tests passed! But suppose that palindrome_e() returned the wrong answer for the empty string "", then a test would fail.
$ perl ptest.t ... ok 3 not ok 4 # Test 4 got: "" (ptest.t at line 36) # Expected: "1" (palindrome_e: "" should be a palindrome.) # ptest.t line 36 is: ok palindrome_e == $expect, 1, "palindrome_e: $note"; ok 5 ...
$ prove ptest.t ptest.t .. 1/24 # Test 4 got: "" (ptest.t at line 36) # Expected: "1" (palindrome_e: "" should be a palindrome.) # ptest.t line 36 is: ok palindrome_e == $expect, 1, "palindrome_e: $note"; ptest.t .. Failed 1/24 subtests Test Summary Report ------------------- ptest.t (Wstat: 0 Tests: 24 Failed: 1) Failed test: 4 Files=1, Tests=24, 0 wallclock secs ( 0.02 usr 0.01 sys + 0.02 cusr 0.00 csys = 0.05 CPU) Result: FAIL
Perl 6
<lang perl6>use Test;
my %tests =
'A man, a plan, a canal: Panama.' => True, 'My dog has fleas' => False, "Madam, I'm Adam." => True, '1 on 1' => False, 'In girum imus nocte et consumimur igni' => True, => True, ;
plan %tests.elems;
for %tests.kv -> $test, $expected-result {
is palin($test), $expected-result, "\"$test\" is {$expected-result??!!'not '}a palindrome.";
}</lang>
Output:
1..6 ok 1 - "1 on 1" is not a palindrome. ok 2 - "My dog has fleas" is not a palindrome. ok 3 - "A man, a plan, a canal: Panama." is a palindrome. ok 4 - "" is a palindrome. ok 5 - "Madam, I'm Adam." is a palindrome. ok 6 - "In girum imus nocte et consumimur igni" is a palindrome.
PicoLisp
The 'test' function is built into PicoLisp. <lang PicoLisp>(de palindrome? (S)
(= (setq S (chop S)) (reverse S)) )
(test T (palindrome? "racecar")) (test NIL (palindrome? "ferrari"))</lang>
PureBasic
PureBasic allows for definition of Assert() and other tools & the debugger is integrated into the native editor. <lang PureBasic>Macro DoubleQuote
; Needed for the Assert-Macro below " ; " second dlbquote to prevent Rosettas misshighlighting of following code. Remove comment before execution!
EndMacro Macro Assert(TEST,MSG="")
CompilerIf #PB_Compiler_Debugger If Not (TEST) If MSG<>"": Debug MSG: EndIf Temp$="Fail: "+DoubleQuote#TEST#DoubleQuote Debug Temp$+", Line="+Str(#PB_Compiler_Line)+" in "+#PB_Compiler_File CallDebugger EndIf CompilerEndIf
EndMacro
Procedure IsPalindrome(StringToTest.s)
If StringToTest=ReverseString(StringToTest) ProcedureReturn 1 Else ProcedureReturn 0 EndIf
EndProcedure
text1$="racecar" text2$="wisconsin" Assert(IsPalindrome(text1$), "Catching this would be a fail") Assert(IsPalindrome(text2$), "Catching this is correct")</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
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>
Retro
Retro includes a library for creating automated tests. This is used for checking the standard libraries shipped with Retro.
<lang Retro>needs assertion' needs hash'
- palindrome? ( $-f ) dup ^hash'hash [ ^strings'reverse ^hash'hash ] dip = ;
with assertion'
- t0 ( - ) "hello" palindrome? 0 assert= ; assertion
- t1 ( - ) "ingirumimusnocteetconsumimurigni" palindrome? -1 assert= ; assertion
- test ( - ) t0 t1 ;
test</lang>
Ruby
test/unit
Ruby comes with a 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
minitest
Many Ruby hackers have switched from 'test/unit' to other testing libraries. Some of these libraries provide the 'describe' block, which is just a pretty way to make a test case. RSpec, Bacon and minitest are such libraries.
This example uses Minitest, which comes with Ruby 1.9. (But if you have Ruby 1.8, then you can still install Minitest as a gem, using RubyGems.)
<lang ruby># palindrome.rb def palindrome?(s)
s == s.reverse
end
require 'minitest/spec' require 'minitest/autorun' describe "palindrome? function" do
it "returns true if arg is a palindrome" do (palindrome? "aba").must_equal true end it "returns false if arg is not a palindrome" do palindrome?("ab").must_equal false end
it "raises NoMethodError if arg is without #reverse" do proc { palindrome? 42 }.must_raise NoMethodError end
it "raises ArgumentError if wrong number of args" do proc { palindrome? "a", "b" }.must_raise ArgumentError end
it "passes a failing test" do palindrome?("ab").must_equal true, "this test case fails on purpose" end
end</lang>
$ ruby19 palindrome.rb Loaded suite palindrome Started ..F.. Finished in 0.000629 seconds. 1) Failure: test_0005_passes_a_failing_test(PalindromeFunctionSpec) [palindrome.rb:26]: this test case fails on purpose. Expected false, not true. 5 tests, 5 assertions, 1 failures, 0 errors, 0 skips Test run options: --seed 40770
Scala
There are three main Scala testing libraries: ScalaCheck, ScalaTest and Specs. The first is shown here, being similar to Haskell's QuickCheck.
<lang scala>import org.scalacheck._ import Prop._ import Gen._
object PalindromeCheck extends Properties("Palindrome") {
property("A string concatenated with its reverse is a palindrome") = forAll { s: String => isPalindrome(s + s.reverse) } property("A string concatenated with any character and its reverse is a palindrome") = forAll { (s: String, c: Char) => isPalindrome(s + c + s.reverse) } property("If the first half of a string is equal to the reverse of its second half, it is a palindrome") = forAll { (s: String) => s.take(s.length / 2) != s.drop((s.length + 1) / 2).reverse || isPalindrome(s) } property("If the first half of a string is different than the reverse of its second half, it isn't a palindrome") = forAll { (s: String) => s.take(s.length / 2) == s.drop((s.length + 1) / 2).reverse || !isPalindrome(s) }
}</lang>
Output:
+ Palindrome.A string concatenated with its reverse is a palindrome: OK, pa ssed 100 tests. + Palindrome.A string concatenated with any character and its reverse is a palindrome: OK, passed 100 tests. + Palindrome.If the first half of a string is equal to the reverse of its s econd half, it is a palindrome: OK, passed 100 tests. + Palindrome.If the first half of a string is different than the reverse of its second half, it isn't a palindrome: OK, passed 100 tests.
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.
<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.