A Library as a Framework for testing and timing

Hello.

I have moved the test framework over to its own post, as it is really a stand-alone thing.

It is very easy to use, and can be used for a variety of stuff, like writing a test suite, that you can program towards, so that at least all your handlers are ready when all the tests are passed.

Or as a final integration test, that you run the test suite after you have made changes, to check that everything still works as it should.

Maybe you’ll have to play a little bit with this to grasp it, but it should be fairly simple, and should pay off really well.

You’ll need to have installed getMillisec in order to use this, and know that it is working.

We are not using millisecs in these tests, we are on the other hand using ticks:

Ticks are better! milliseconds / 10 = hundreths, there can be 100 ticks in a second, if the form of ticks you deal with is of this kind.

If you really want to deal with ticks of the old kind which where 1/60th of a second, then you can divide the milliseconds by 100 and multiply by 6, which is what I have done here, to provide for some consistency

Maybe you’ll get the idea of how you can utilize the test library, by reading through the code below, I think you will.

Below are some references, before the Library script that you’ll have to install in your Script Libraries folder, and after that a short demo script, to give you some ideas.

And there are handlers in the Script Library, that makes it really easy to test out algorithms.

References

This an in-depth article about AppleScript’s Variable types and you. where I stumbled upon the test framework.

The test script I found here has a caveat though. Be warned: you must remove all calls and references to simpleAddSelfToEndOfSelfErr() since it will crash AppleScript editor!

If you want to know slightly more about unit testing, then this article may be of great interest.

There is also a page or two about the same test framework over at DrDobbs but be prepared to give away your email address in order to create an account/sign in.

About the code:

This code is shamelessl stoleny from Ryan Wilcox, (see reference above). As usual all faults are mine.

This script doesn’t have to be saved as a bundle. No terminolgy here either, as this is for development.

I hope you find it useful. :slight_smile:

-- This is totally stolen from Ryan Wilcox, and reworked, just a little bit
-- so that the handler for ticks has been replaced with getMillisec
-- and that this code has been prepared for AppleScript version 2.3
-- I have also removed his test results for the various handlers.
-- I have changed the usage of testHandlers into test scripts, to make it easier
-- to reuse, I have have also done any modifications necessary so that
-- the framework can be put into an AppleScript 2.3 Library.
-- I have called the Library "RyanWilcox" and uses
--
-- use Wilcox : script "RyanWilcox"
--
-- to call it. (This Library should be saved as a script file in your
-- ScriptLibraries folder.) See example below for usage:
-- The idea is that you write a test script (at least, for testing one of
-- your handlers, whether it be in a regular script or library, in a 
-- *separate script* that you run to test the integrity of your library/script
-- as you add more handlers, or change stuff.
-- You'll get the hang of it, if this is something that suits you! ;)
-- Rev2: added a method to run many test suites: there can be many suites in 
-- one unit. 
-- rev3: Added a method to log stuff _log, removed the printing of fail, when 
-- nothing has failed. Optimized the "printing" with TextEdit.
-- The window with the results now pop up automatically over the test script that ran.
property parent : AppleScript
use AppleScript version "2.3"
use scripting additions
use McUsr : script "TimerTools"
use output : script "Output"
property numberTestsThatHaveRun : 0
property numberTestsThatHavePassed : 0
property numberTestsThatHaveFailed : 0
property processFile : 0

-- ---------------------- User control properties ---------------------- --
property doTimings : true

-- ----------------------- Utility Functions ---------------------- --
to getMinimumOf(lst)
	set currSmaller to item 1 of lst
	repeat with each in lst
		if (each < currSmaller) then
			set currSmaller to each
		end if
	end repeat
	return contents of currSmaller
end getMinimumOf

to getMaximumOf(lst) (*950*)
	set currSmaller to item 1 of lst
	repeat with each in lst
		if (each > currSmaller) then
			set currSmaller to each
		end if
	end repeat
	return contents of currSmaller
end getMaximumOf

on getAverageOf(lst)
	set total to 0
	set nums to number of items in lst
	
	repeat with each in lst
		set total to total + each
	end repeat
	set average to total / nums
	return average
end getAverageOf (*969*)



to _result(beforeText, testName, afterText)
	local testInfo
	set testInfo to beforeText & testName & " (" & afterText & ")"
	output's writeLn(testInfo)
end _result

-- ----------------------- Framework stuff ---------------------- --
-- Novelty: _log statement:

on _log(theText)
	output's writeLn("==> " & theText)
end _log


on _test(testPassed, testName) (*979*)
	set numberTestsThatHaveRun to numberTestsThatHaveRun + 1
	set textStatus to ""
	
	if (testPassed) then
		set numberTestsThatHavePassed to numberTestsThatHavePassed + 1
		set textStatus to "passed"
	else
		set numberTestsThatHaveFailed to numberTestsThatHaveFailed + 1
		set textStatus to "failed"
	end if
	
	_result("tested: ", testName, textStatus)
end _test



on _time(iters, theTest, testName)
	if doTimings then
		set durations to {}
		
		repeat with i from 1 to iters
			set startTime to the (McUsr's getMillisec()) / 10 * 6
			
			run theTest
			set endTime to (McUsr's getMillisec()) / 10 * 6
			
			set ourDuration to endTime - startTime
			set end of durations to ourDuration
		end repeat
		set minTime to getMinimumOf(durations)
		set avgTime to getAverageOf(durations)
		set maxTime to getMaximumOf(durations)
		
		_result("timed: ", testName, "min: " & minTime & ", max: " & maxTime & ", avg: " & avgTime)
	else
		_result("timing for: ", testName, "skipped")
	end if
end _time

to _timeTest(iters, theTest, testName)
	_test(run theTest, testName)
	_time(iters - 1, theTest, testName)
end _timeTest


on initFramework()
	output's reset()
	output's init(("Test Run starting at " & (current date) as string) & return, 600, 800)
	output's bringToFront()
end initFramework

to displayFinalMessage(msg, unitName)
	display notification msg with title "Wilcox's Testsuite" subtitle unitName
end displayFinalMessage

on terminateFramework()
	
	output's writeLn(return & return & ¬
		"===============================" & return & "Number of tests ran: " & numberTestsThatHaveRun ¬
		& return & "Number of tests failed: " & numberTestsThatHaveFailed)
	
	--take care to reset our properties
	set numberTestsThatHaveRun to 0
	set numberTestsThatHavePassed to 0
	set numberTestsThatHaveFailed to 0
	set testRunner to missing value
	output's leaveAtFront(2)
end terminateFramework


on runTestSuite(testsToRun, unitName)
	initFramework()
	run testsToRun
	set messageStr to ((("Ran " & numberTestsThatHaveRun as string) & " tests. " & numberTestsThatHavePassed as string) & " passed, " & numberTestsThatHaveFailed as string) & " tests failed."
	tell me to activate -- switch back to this app for the user
	displayFinalMessage(messageStr, unitName)
	terminateFramework()
end runTestSuite

-- You are suppose to initialize the framework up front
-- and take it down afterwards.
-- we do keep track of the total number of tests and everything here.

on runManyTestSuites(testSuitesToRun, testSuitNames, unitName)
	local totRuns, totPassed, totFails, idx
	set {totRuns, totPassed, totFails, idx} to {0, 0, 0, 1}
	initFramework()
	repeat with testsToRun in testSuitesToRun
		run testsToRun
		-- Novelty: no printing of "0 failed"
		if numberTestsThatHaveFailed > 0 then
			set messageStr to ((("Testing " & item idx of testSuitNames & ":" & linefeed & "Ran " & numberTestsThatHaveRun as string) & " tests. " & numberTestsThatHavePassed as string) & " passed." & numberTestsThatHaveFailed as string) & " tests failed."
		else
			set messageStr to ((("Testing " & item idx of testSuitNames & ":" & linefeed & "Ran " & numberTestsThatHaveRun as string) & " tests. " & numberTestsThatHavePassed as string) & " passed.")
		end if
		-- _PRINT(return & messageStr & return)
		output's writeLn(return & messageStr & return)
		set {totRuns, numberTestsThatHaveRun, idx} to {totRuns + numberTestsThatHaveRun, 0, idx + 1}
		set {totPassed, numberTestsThatHavePassed} to {totPassed + numberTestsThatHavePassed, 0}
		set {totFails, numberTestsThatHaveFailed} to {totFails + numberTestsThatHaveFailed, 0}
	end repeat
	if totFails > 0 then
		set messageStr to ((("Total: " & totRuns as string) & " tests." & totPassed as string) & " tests passed, " & totFails as string) & " tests failed."
	else
		set messageStr to ((("Total: " & totRuns as string) & " tests." & totPassed as string) & " tests passed.")
	end if
	
	tell me to activate -- switch back to this app for the user (that runs this script..)
	displayFinalMessage(messageStr, unitName)
	set {numberTestsThatHaveRun, numberTestsThatHaveFailed} to {totRuns, totFails}
	terminateFramework()
end runManyTestSuites


This is an example simple usage, check out post #4 for a more realistic example.

 use AppleScript version "2.3"
use scripting additions
use Wilcox : script "RyanWilcox"

-- this is a demonstration script of unit testing in AppleScript.

script mytest1
	-- This would be a test for a real handler,
	-- that you wrote a test for that returned true
	-- if it passed, or false if it failed.
	if (3 + 4) = 7 then
		return true
	else
		return false
	end if
end script

script mytest2
	-- This would be a test for a real handler,
	-- that you wrote a test for that returned true
	-- if it passed, or false if it failed.
	if (10 / 5) = 2 then
		return true
	else
		return false
	end if
end script

script testsToRun
	-- Wilcox's currHandlerToTest
	Wilcox's _test(run mytest1, "my first Test")
	
	Wilcox's _test(run mytest2, "my second test")
	-- demo of timing:
	Wilcox's _time(100, my mytest1, "my first Test")
	Wilcox's _time(100, my mytest2, "my second Test")
end script

-- This is a template function that is to be used in every test.

Wilcox's runTestSuite(testsToRun, "Concept Test")

Enjoy!

Hello.

When using the framework above, then you’ll of course feed your handlers some data, that leads to a result you know what should be, and that is what you test for, and if it doesn’t then it has failed the test.

When, and if your code still failed, even if you have passed your test, then you must go back and either write another test for that case, or expand your test case. The wise guy’s says you should test each logical branch in your code, but this can be a little too much, so it is better to at least test for something, than nothing.

And all of this extranous work, -may occasionally save the day, when you acutally discover a bug! It is also a much more efficient way to test code, than walking through it in a Debugger/Explorer, which in some cases are an indispensable tool, for finding culprits.

Happy Coding!

Hello.

I have added the line property parent : AppleScript into the Wilcox testsuite Library. Because I got some strange error number -4960, when running it from AppleScript Editor with a little bit more than two tests.
I guess the more I use this, the more I am going to sprinkle the various test objects with that property. But that’s life!
Apropos:
:smiley: My venerable Script Debugger 4.5.7 handles the new syntax, now, how cool isn’t that?

Hello.

Using this a littlebit, I found the model to be a little bit inflexible, with regards to everything. Having given it some thought, I ended up with adding a method runManyTestSuites under the pretext that there can be many testsuites for one unit.

With the risk of littering, I here present, something that should go for a “real” example of usage, together with the output ( in opposite order, to give you some ideas.)

property parent : AppleScript
use AppleScript version "2.3"
use scripting additions
use Wilcox : script "RyanWilcox"


script trigs
	
	property parent : AppleScript
	property degrad : pi / 180
	
	on rev(x)
		tell (x)
			return it - ((it div 360.0) * 360.0) + ((it < 0) as integer) * 360
		end tell
	end rev
	
	on cosd(x)
		return cos (x * degrad)
	end cosd
	
	on sind(x)
		return (sin (x * degrad))
	end sind
	
	on asind(x)
		return ((asin (x)) / degrad)
	end asind
end script
-- this is a demonstration script of unit testing in AppleScript.
on JD(yr, mt, dy)
	# Julian day number, + 12 hours, so you won't have to adjust for the 
	# surplus of 12 hours, this julian day starts at ut0h, not ut-12h.
	return (367.0 * yr - (7.0 * (yr + ((mt + 9.0) / 12.0))) / 4.0 + (275.0 * mt) / 9.0 + dy - 7.3053E+5) div 1
end JD

script julianTest
	
	if JD(1990, 4, 19) = -3543.0 then
		return true
	else
		return false
	end if
end script

-- ===========================================

script planets
	property N : 0
	property i_ : 0
	property w : 0
	property a : 0
	property e_ : 0
	property m_ : 0
	
	(*
	on ComputeOrbitalElements(D, sun_ls)
		set N to longOfMoonsAscNode(D)
		set w to MoonsArgOfPerigee(D)
		set m to MoonsMeanAnamoly(D)
		set lm to util's rev(N + w + m)
		set F_ to util's rev(w + m)
		set E_ to MoonsEccAnamoly(m, e)
		local x_lunOrb, y_lunOrb
		# rectangular coordinates in the plane of the lunar orbit
		set x_lunOrb to a * ((cos E_ * (util's degrad)) - e)
		set y_lunOrb to a * ((1 - e * e) ^ 0.5) * (sin E_ * (util's degrad))
		set r to (x_lunOrb * x_lunOrb + y_lunOrb * y_lunOrb) ^ 0.5
		set v to util's rev(180 / pi * (atan2 {y_lunOrb, x_lunOrb}))
		set D_ to lm - sun_ls
	end ComputeOrbitalElements
	*)
	-- primitives for computing Kepler's elements
	on setLongAscNode(primDegArg, secDegArg, theJd)
		set my N to trigs's rev(primDegArg + secDegArg * theJd)
	end setLongAscNode
	
	on getLongAscNode()
		return my N
	end getLongAscNode
	
	on setInclination(primDegArg, secDegArg, theJd)
		set my i_ to primDegArg + secDegArg * theJd
	end setInclination
	
	on getInclination()
		return my i_
	end getInclination
	
	on setArgOfPerihelion(primDegArg, secDegArg, theJd)
		set my w to primDegArg + secDegArg * theJd
	end setArgOfPerihelion
	
	on getArgOfPerihelion()
		return my w
	end getArgOfPerihelion
	
	on setSemiMajorAxis(theArg)
		set my a to theArg
	end setSemiMajorAxis
	
	on getSemiMajorAxis()
		return my a
	end getSemiMajorAxis
	
	on setEccentricity(primArg, secArg, theJd)
		set my e_ to primArg + secArg * theJd
	end setEccentricity
	
	on getEccentricity()
		return my e_
	end getEccentricity
	
	on setMeanAnamoly(primArg, secArg, theJd)
		set my m_ to trigs's rev(primArg + secArg * theJd)
	end setMeanAnamoly
	
	on getMeanAnamoly()
		return my m_
	end getMeanAnamoly
	
	on compOrbElements()
		return my lonPeriHelion()
	end compOrbElements
	
	on getN()
		return my N
	end getN
	
end script

on makePlanet()
	script planet
		property parent : planets
		property N : 0
		property i_ : 0
		property w : 0
		property a : 0
		property e_ : 0
		property m_ : 0
		
	end script
end makePlanet

script uranus
	property parent : planets
	property N : 0
	property i_ : 0
	property w : 0
	property a : 0
	property e_ : 0
	property m_ : 0
	
	on setSemiMajorAxis(primArg, secArg, theJd)
		set my a to trigs's rev(primArg + secArg * theJd)
	end setSemiMajorAxis
	
end script

script neptune
	property parent : uranus
	property N : 0
	property i_ : 0
	property w : 0
	property a : 0
	property e_ : 0
	property m_ : 0
	
end script

global mjd

set mjd to -3543.0

global mercury
script mercuryTest1
	set mercury to makePlanet()
	mercury's setLongAscNode(48.3313, 3.24587E-5, mjd)
	
	if (abs ((mercury's getLongAscNode()) - 48.2163)) < 1.0E-5 then
		return true
	else
		return false
	end if
end script

script mercuryTest2
	mercury's setInclination(7.0047, 5.0E-8, mjd)
	if (abs ((mercury's getInclination()) - 7.0045)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script mercuryTest3
	mercury's setArgOfPerihelion(29.1241, 1.01444E-5, mjd)
	if (abs ((mercury's getArgOfPerihelion()) - 29.0882)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script mercuryTest4
	mercury's setSemiMajorAxis(0.387098)
	if (abs ((mercury's getSemiMajorAxis()) - 0.387098)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script mercuryTest5
	mercury's setEccentricity(0.205635, 5.59E-10, mjd)
	if (abs ((mercury's getEccentricity()) - 0.205633)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script mercuryTest6
	mercury's setMeanAnamoly(168.6562, 4.0923344368, mjd)
	if (abs ((mercury's getMeanAnamoly()) - 69.5153)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

global venus

script venusTest1
	set venus to makePlanet()
	venus's setLongAscNode(76.6799, 2.4659E-5, mjd)
	-- This would be a test for a real handler,
	-- that you wrote a test for that returned true
	-- if it passed, or false if it failed.
	if (abs ((venus's getLongAscNode()) - 76.5925)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script venusTest2
	venus's setInclination(3.3946, 2.75E-8, mjd)
	if (abs ((venus's getInclination()) - 3.3945)) < 1.0E-5 then
		return true
	else
		return false
	end if
end script

script venusTest3
	venus's setArgOfPerihelion(54.891, 1.38374E-5, mjd)
	if (abs ((venus's getArgOfPerihelion()) - 54.842)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script venusTest4
	venus's setSemiMajorAxis(0.72333)
	if (abs ((venus's getSemiMajorAxis()) - 0.72333)) < 1.0E-5 then
		return true
	else
		return false
	end if
end script

script venusTest5
	venus's setEccentricity(0.006773, -1.302E-9, mjd)
	if (abs ((venus's getEccentricity()) - 0.006778)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script venusTest6
	venus's setMeanAnamoly(48.0052, 1.6021302244, mjd)
	if (abs ((venus's getMeanAnamoly()) - 131.6578)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

global mars

script marsTest1
	set mars to makePlanet()
	mars's setLongAscNode(49.5574, 2.11081E-5, mjd)
	-- This would be a test for a real handler,
	-- that you wrote a test for that returned true
	-- if it passed, or false if it failed.
	if (abs ((mars's getLongAscNode()) - 49.4826)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script marsTest2
	mars's setInclination(1.8497, -1.78E-8, mjd)
	if (abs ((mars's getInclination()) - 1.8498)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script marsTest3
	mars's setArgOfPerihelion(286.5016, 2.92961E-5, mjd)
	if (abs ((mars's getArgOfPerihelion()) - 286.3978)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script marsTest4
	mars's setSemiMajorAxis(1.523688)
	if (abs ((mars's getSemiMajorAxis()) - 1.523688)) < 1.0E-5 then
		return true
	else
		return false
	end if
end script

script marsTest5
	mars's setEccentricity(0.093405, 2.516E-9, mjd)
	if (abs ((mars's getEccentricity()) - 0.093396)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script marsTest6
	mars's setMeanAnamoly(18.6021, 0.5240207766, mjd)
	if (abs ((mars's getMeanAnamoly()) - 321.9965)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

global jupiter

script jupiterTest1
	set jupiter to makePlanet()
	jupiter's setLongAscNode(100.4542, 2.76854E-5, mjd)
	-- This would be a test for a real handler,
	-- that you wrote a test for that returned true
	-- if it passed, or false if it failed.
	if (abs ((jupiter's getLongAscNode()) - 100.3561)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script jupiterTest2
	jupiter's setInclination(1.303, -1.557E-7, mjd)
	if (abs ((jupiter's getInclination()) - 1.3036)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script jupiterTest3
	jupiter's setArgOfPerihelion(273.8777, 1.64505E-5, mjd)
	if (abs ((jupiter's getArgOfPerihelion()) - 273.8194)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script jupiterTest4
	jupiter's setSemiMajorAxis(5.20256)
	if (abs ((jupiter's getSemiMajorAxis()) - 5.20256)) < 1.0E-5 then
		return true
	else
		return false
	end if
end script

script jupiterTest5
	jupiter's setEccentricity(0.048498, 4.469E-9, mjd)
	if (abs ((jupiter's getEccentricity()) - 0.048482)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script jupiterTest6
	jupiter's setMeanAnamoly(19.895, 0.0830853001, mjd)
	if (abs ((jupiter's getMeanAnamoly()) - 85.5238)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script


global saturn

script saturnTest1
	set saturn to makePlanet()
	saturn's setLongAscNode(113.6634, 2.3898E-5, mjd)
	-- This would be a test for a real handler,
	-- that you wrote a test for that returned true
	-- if it passed, or false if it failed.
	if (abs ((saturn's getLongAscNode()) - 113.5787)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script saturnTest2
	saturn's setInclination(2.4886, -1.081E-7, mjd)
	if (abs ((saturn's getInclination()) - 2.489)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script saturnTest3
	saturn's setArgOfPerihelion(339.3939, 2.97661E-5, mjd)
	if (abs ((saturn's getArgOfPerihelion()) - 339.2884)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script saturnTest4
	saturn's setSemiMajorAxis(9.55475)
	if (abs ((saturn's getSemiMajorAxis()) - 9.55475)) < 1.0E-5 then
		return true
	else
		return false
	end if
end script

script saturnTest5
	saturn's setEccentricity(0.055546, -9.499E-9, mjd)
	if (abs ((saturn's getEccentricity()) - 0.05558)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script saturnTest6
	saturn's setMeanAnamoly(316.967, 0.0334442282, mjd)
	if (abs ((saturn's getMeanAnamoly()) - 198.4741)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script



script uranusTest1
	--	set uranus to makePlanet()
	uranus's setLongAscNode(74.0005, 1.3978E-5, mjd)
	-- This would be a test for a real handler,
	-- that you wrote a test for that returned true
	-- if it passed, or false if it failed.
	if (abs ((uranus's getLongAscNode()) - 73.951)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script uranusTest2
	uranus's setInclination(0.7733, 1.9E-8, mjd)
	if (abs ((uranus's getInclination()) - 0.7732)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script uranusTest3
	uranus's setArgOfPerihelion(96.6612, 3.0565E-5, mjd)
	if (abs ((uranus's getArgOfPerihelion()) - 96.5529)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script uranusTest4
	uranus's setSemiMajorAxis(19.18171, -1.55E-8, mjd)
	if (abs ((uranus's getSemiMajorAxis()) - 19.18176)) < 1.0E-5 then
		return true
	else
		return false
	end if
end script

script uranusTest5
	uranus's setEccentricity(0.047318, 7.45E-9, mjd)
	if (abs ((uranus's getEccentricity()) - 0.047292)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script uranusTest6
	uranus's setMeanAnamoly(142.5905, 0.011725806, mjd)
	if (abs ((uranus's getMeanAnamoly()) - 101.046)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script neptuneTest1
	--	set neptune to makePlanet()
	neptune's setLongAscNode(131.7806, 3.0173E-5, mjd)
	-- This would be a test for a real handler,
	-- that you wrote a test for that returned true
	-- if it passed, or false if it failed.
	if (abs ((neptune's getLongAscNode()) - 131.6737)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script neptuneTest2
	neptune's setInclination(1.77, -2.55E-7, mjd)
	if (abs ((neptune's getInclination()) - 1.7709)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script neptuneTest3
	neptune's setArgOfPerihelion(272.8461, -6.027E-6, mjd)
	if (abs ((neptune's getArgOfPerihelion()) - 272.8675)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script neptuneTest4
	neptune's setSemiMajorAxis(30.05826, 3.313E-8, mjd)
	if (abs ((neptune's getSemiMajorAxis()) - 30.05814)) < 1.0E-5 then
		return true
	else
		return false
	end if
end script

script neptuneTest5
	neptune's setEccentricity(0.008606, 2.15E-9, mjd)
	if (abs ((neptune's getEccentricity()) - 0.008598)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script

script neptuneTest6
	neptune's setMeanAnamoly(260.2471, 0.005995147, mjd)
	if (abs ((neptune's getMeanAnamoly()) - 239.0063)) < 1.0E-4 then
		return true
	else
		return false
	end if
end script
local theSuites, theSuiteNames

set {theSuites, theSuiteNames} to {{}, {}}

script mercuryTestsToRun
	-- Wilcox's currHandlerToTest
	Wilcox's _test(run julianTest, "Test of Julian Dates")
	
	Wilcox's _test(run mercuryTest1, "Longitude of ascending node of mercury")
	Wilcox's _test(run mercuryTest2, "inclination of mercury")
	
	Wilcox's _test(run mercuryTest3, "Mercury's argument of Perihelion")
	Wilcox's _test(run mercuryTest4, "Mercury's semi major axis")
	Wilcox's _test(run mercuryTest5, "Mercury's eccentricity")
	Wilcox's _test(run mercuryTest6, "Mercury's mean Anamoly")
end script
set {end of theSuites, end of theSuiteNames} to {mercuryTestsToRun, "Orbital elements of Mercury"}
script venusTestsToRun
	-- Wilcox's currHandlerToTest
	
	Wilcox's _test(run venusTest1, "Longitude of ascending node of venus")
	Wilcox's _test(run venusTest2, "inclination of venus")
	
	Wilcox's _test(run venusTest3, "venus's argument of Perihelion")
	Wilcox's _test(run venusTest4, "venus's semi major axis")
	Wilcox's _test(run venusTest5, "venus's eccentricity")
	Wilcox's _test(run venusTest6, "venus's mean Anamoly")
end script
set {end of theSuites, end of theSuiteNames} to {venusTestsToRun, "Orbital elements of Venus"}
script marsTestsToRun
	-- Wilcox's currHandlerToTest
	
	Wilcox's _test(run marsTest1, "Longitude of ascending node of mars")
	Wilcox's _test(run marsTest2, "inclination of mars")
	
	Wilcox's _test(run marsTest3, "mars's argument of Perihelion")
	Wilcox's _test(run marsTest4, "mars's semi major axis")
	Wilcox's _test(run marsTest5, "mars's eccentricity")
	Wilcox's _test(run marsTest6, "mars's mean Anamoly")
end script
set {end of theSuites, end of theSuiteNames} to {marsTestsToRun, "Orbital elements of Mars"}
script jupiterTestsToRun
	-- Wilcox's currHandlerToTest
	
	Wilcox's _test(run jupiterTest1, "Longitude of ascending node of jupiter")
	Wilcox's _test(run jupiterTest2, "inclination of jupiter")
	
	Wilcox's _test(run jupiterTest3, "jupiter's argument of Perihelion")
	Wilcox's _test(run jupiterTest4, "jupiter's semi major axis")
	Wilcox's _test(run jupiterTest5, "jupiter's eccentricity")
	Wilcox's _test(run jupiterTest6, "jupiter's mean Anamoly")
end script
set {end of theSuites, end of theSuiteNames} to {jupiterTestsToRun, "Orbital elements of Jupiter"}

script saturnTestsToRun
	-- Wilcox's currHandlerToTest
	
	Wilcox's _test(run saturnTest1, "Longitude of ascending node of saturn")
	Wilcox's _test(run saturnTest2, "inclination of saturn")
	
	Wilcox's _test(run saturnTest3, "saturn's argument of Perihelion")
	Wilcox's _test(run saturnTest4, "saturn's semi major axis")
	Wilcox's _test(run saturnTest5, "saturn's eccentricity")
	Wilcox's _test(run saturnTest6, "saturn's mean Anamoly")
end script
set {end of theSuites, end of theSuiteNames} to {saturnTestsToRun, "Orbital elements of Saturn"}
script uranusTestsToRun
	-- Wilcox's currHandlerToTest
	
	Wilcox's _test(run uranusTest1, "Longitude of ascending node of uranus")
	Wilcox's _test(run uranusTest2, "inclination of uranus")
	
	Wilcox's _test(run uranusTest3, "uranus's argument of Perihelion")
	Wilcox's _test(run uranusTest4, "uranus's semi major axis")
	Wilcox's _test(run uranusTest5, "uranus's eccentricity")
	Wilcox's _test(run uranusTest6, "uranus's mean Anamoly")
end script
set {end of theSuites, end of theSuiteNames} to {uranusTestsToRun, "Orbital elements of Uranus"}
script neptuneTestsToRun
	-- Wilcox's currHandlerToTest
	
	Wilcox's _test(run neptuneTest1, "Longitude of ascending node of neptune")
	Wilcox's _test(run neptuneTest2, "inclination of neptune")
	
	Wilcox's _test(run neptuneTest3, "neptune's argument of Perihelion")
	Wilcox's _test(run neptuneTest4, "neptune's semi major axis")
	Wilcox's _test(run neptuneTest5, "neptune's eccentricity")
	Wilcox's _test(run neptuneTest6, "neptune's mean Anamoly")
end script

set {end of theSuites, end of theSuiteNames} to {neptuneTestsToRun, "Orbital elements of Neptune"}
-- This is a template function that is to be used in every test.

-- tell Wilcox to runTestSuite(mercuryTestsToRun, "Orbital elements of Mercury")
-- tell Wilcox to runTestSuite(venusTestsToRun, "Orbital elements of venus")
-- tell Wilcox to runTestSuite(marsTestsToRun, "Orbital elements of mars")
--tell Wilcox to runTestSuite(jupiterTestsToRun, "Orbital elements of jupiter")
--tell Wilcox to runTestSuite(saturnTestsToRun, "Orbital elements of saturn")
--tell Wilcox to runTestSuite(uranusTestsToRun, "Orbital elements of uranus")
-- tell Wilcox to runTestSuite(neptuneTestsToRun, "Orbital elements of neptune")
tell Wilcox to runManyTestSuites(theSuites, theSuiteNames, "The Planets")
error number -128

Hello.

* I have added a method to log stuff: _log, so you don’t have to add/remove log statements from your script, nor have to read the log window of your favourite editor, while looking at the log in Text Edit.

Example:

Wilcox's _log("neptune GeocentricHourAngle" & probe & "neptune's RA: " & probe2)

* Seeing all those “Fails: 0” bugged me, so I removed the printing of fail, when nothing has failed. I also optimized the “printing” with TextEdit. (Inserting a paragraph insted of concatenating the text of its front document with some new text actually speeded up things considerable.)

* Lastly: the window with the results now pop up automatically over the test script that ran.

There is also a great video called Testing in XCode that is highly recommended to watch. You’ll need a Developer Account, but it is free. :slight_smile:

Hello.

The version below uses the new ConsoleIO Library which you need to download and install in your ~/Library/Script Libraries folder. (You also need to run Mavericks). This should provide for more possiblities, regarding output, should you wish to roll your own solution. I have something on the bedding, with files saved with a number, ascending, and Filemerge, but I haven’t tested it fully out yet.

I really shouldn’t say that this should be a great tool for testing the object model of a scriptable app, but I think it is. :slight_smile:

You should be able to somehow, (after some adjustments) be able to run this as a task under Xcode for testing the scriptability of an object model, under a test scheme.

I have used this a lot now, for testing object models, and it has been great. If you are unfamiliar with unit testing, then I encourage you to watch Apple’s wwdc videos on the subject.

This is not good for testing UI, but it is good for testing handlers and data, that represents the model part of the model view controller pattern, and should also be good for testing the interaction with the controller, and maybe parts of the controller to. But trying this on the UI/View, seems very impractical.

Hello.

I have forgotten to mention this; the testing framework should of course also be very useful when adding scripting terminology to a library. To check that it all works as it should. :slight_smile: