Re: "proper" way to handle "global" data
On Dec 18, 10:42 pm, Arne Vajh=F8j <a...@vajhoej.dk> wrote:
Aryeh M. Friedman wrote:
public class Settings
{
public void addSetting(String key,Object val)
{
map.put(key,val);
}
public Object getSetting(String key)
{
return map.get(key);
}
private static Map<String,Object> map=new
HashMap<String,Object>();
}
even though this works I am starting to have bugs due to the fact the
data global.... for example when I go to count the number of tests in
a test set (so I can create a progress bar that actually shows
progress) the results get totally scrambled because each test has a
local copy of it's own the results and some other things (just in
typing this I realized that run() should not also construct the test
list [it will do it twice if you pre-count])
I am not sure that I understand your problem description.
But the non-static methods updating a static map look very
funky to me.
Since I am on a different machine then I wrote the example code from
memory the methods are static also. The problem was that if you write
something assuming no statics at all sometimes it get garbled when you
convert to a static is very a decent way to keep this from happening
(in this case like I said move the initialization to the ctor and
since that is only called once it solves the problem of double adding
some thins). Since I have since switched machines here is the cut and
pasted compile time version:
package dev.thistest.core;
import java.util.HashMap;
import java.util.Map;
public class Settings
{
public static void addSetting(String key,Object val)
{
init();
map.put(key,val);
}
public static Object getSetting(String key)
{
init();
return map.get(key);
}
public static Map<String,Object> getSettings()
{
init();
return map;
}
private static void init()
{
if(map!=null)
return;
map=new HashMap<String,Object>();
addSetting("RunTest",new Boolean(true));
}
private static Map<String,Object> map;
}
and here is a snippet of a working global in action (RunTest is buggy
right now):
in main():
if(args.length<1)
usage();
Class klass=Loader.load(args[0]);
Object inst=klass.newInstance();
Settings.addSetting("TestType",TestType.All);
Settings.addSetting("EventListener",this);
long start=System.nanoTime();
((Test) inst).run();
System.out.println();
System.out.println("Total running time (seconds): "+
((System.nanoTime()-start)/100000000.0));
printResults(((Test) inst).getResult());
How TestType is used in the actual test code:
private void runType(TestType type)
{
TestType defType=(TestType) Settings.getSetting("TestType");
for(Method m:this.getClass().getDeclaredMethods()) {
if(!canRun(m,type,defType))
continue;
try {
m.invoke(this);
if(type!=TestType.Setup)
getResult().addPass();
} catch(TestException e) {
getResult().addFail(e);
} catch(Throwable e) {
getResult().addNoResult(e);
}
}
}
private boolean canRun(Method m,TestType type,TestType defType)
{
TestCase ann=m.getAnnotation(TestCase.class);
if(ann==null||!Modifier.isPublic(m.getModifiers()))
return false;
if(!ann.value().equals(type))
return false;
if(defType!=TestType.All&&defType!=ann.value()&&ann.value()!
=TestType.Setup)
return false;
if(!(Boolean) Settings.getSetting("RunTest"))
return false;
return true;
}
and EventListener:
private void doTest(Event e)
{
if(report)
listener.testPerformed(e);
}
public Result(boolean report)
{
reset();
this.report=report;
}
public void reset()
{
pass=0;
fail=new ArrayList<TestException>();
noResult=new ArrayList<Throwable>();
listener=(EventListener) Settings.getSetting("EventListener");
}