Wednesday, October 15, 2008
Java Packing
Embedded jars.
Jar files can have class files in them, even resources in them, but not other jar files. Why not? If I have a project that needs a.jar, b.jar, myproject.jar, it would be simpler and easier to jar up the a & b jars into my jar. I’m not saying this is always the best way to go, but it should be an option.
Monkey Patching.
Monkey Patching is the ability to hack out a solution over someone else nice code. Interpreted languages like ruby or php always get this, since you get the source, not a binary. Now there are lots of bad things about Monkey Patching, but it’s really useful when you need it. Now I understand that if you don’t have source, Monkey Patching is not so practical.
However 100% of the jar files I am currently using are Open Source. As such, there should be a standard way of constructing a Jar file so the source is included. Additionally, there should also be easy ways to recompile the jar.
Like: javac recompile a.jar
Again, the jars I’m using are open source, but the ability to easily modify that source is very complex in java. Also, debugging into those classes usually loses source. We need a simpler way to work with the source the jar was made from.
Distilling Minimum class files.
This would also be nice if you could use the jar file the same as regular source path.
For example, let’s say I have a class my1 which uses a1, and a1 uses b1.
(short hand: my1-> a1 -> b1 ) but my source tree has
my1.java
my2.java
a1.java
a2.java
b1.java
b2.java
if I compile my1.java and let javac know my source path,
it’s will follow the links and only give me
my1.class
a1.class
b1.class
Nice right, the minimum needed to run my class. Now think how nice it would be if you had jar files with source attached,
a1 & a2 are in a.jar
b1 & b2 are in b.jar
but still you could get the same results, a jar file with just the minimum needed to run your app.
Right now, there might be a class that i'd like to use, but i'll rewrite it, because i don't want to include the whole jar that it's packaged in. I can't just remove the class file, because it depends on other class files. So I rewrite rather that bloat.
Why should I ever have to make that choice?
Monday, October 13, 2008
Approval Tests (a pictures worth a 1000 tests)
Scenario 1 [Testing a User Interface]
Core Concept :
Component gui = createGui();
Approvals.approve(gui);
This creates a snap shot of the gui: gui.received.png
This passes if gui.received.png == gui.approved.png
If you like the result, simply rename gui.received.png -> gui.approved.png and the test will pass.
Could you explain that in a diagram?
yes.
Why is this awesome?
“a picture is worth a 1000 tests”. Ever find that your unit tests aren’t giving you enough security? Have you started making lots & lots of asserts? Ever find your tests test too many things and the maintenance required to change anything is actually reducing your agility?
Approval Testing gives you 100% lock down on your gui, yet changes simply require a click of a button.
Where are the approved images stored?
Approved images are stored in your testing folder and in your source control. This makes the test repeatable on different systems & you can actually browse a visual of how your gui’s have changed over time!
How does it work for a web app?
String html = createWebPage();
Approvals.approve(html);
Instead of an image, now a text file (page.received.html) is created.
Scenario 2 [Behavior Driven Development]
Core Concept :
Object myObject = createObject();
/*temp*/ Approvals.approve(myObject.toString());
doSomething1();
/*temp*/ Approvals.approve(myObject.toString());
doSomething2();
/*temp*/ Approvals.approve(myObject.toString());
doSomething3();
/*temp*/ Approvals.approve(myObject.toString());
doSomething4();
/*temp*/ Approvals.approve(myObject.toString());
doSomething5();
Approvals.approve(myObject.toString());
As the code is created, the approval will move down, so That the final code is
Object myObject = createObject();
doSomething1();
doSomething2();
doSomething3();
doSomething4();
doSomething5();
Approvals.approve(myObject.toString());
Why is this awesome?
Many times a unit test is scattered with spot testing to assure things are done correctly. This creates a barrier to readability, and can lead to unneeded code.
Approval tests reduce the need to spot check, making the test cleaner and simpler.
What if I don’t want to change my toString?
No problem, create a toOtherString(), or a ObjectWritter, or Inspect the object. Sometimes we even create a ObjectVisualizer when an image is a better way to show the state.
What if there’s a bug in my code?
The first thing to do is to try to walk through your code and get an idea of the state of the object, so you can see where it went wrong... if only you had a nice way of visualizing the state of your object.... oh wait! that’s the first thing you created! I guess it will be pretty easy to debug.
Scenario 3 [The lock down]
Core Concept :
Say I have a web page that displays a user profile. I want to refactor it, but I have no tests. However, I do have 300 users in my current database.
String allPages = getAllUserProfilePages();
Approvals.approve(allPages);
Why is this awesome?
2 lines of code to completely lock down a legacy process. That is the definition of awesome!
Won’t this test be kinda slow?
Yes. But after you are done safely refactoring, you can/should remove the tests.
Is this test data independent? Will it be repeatable tomorrow?
No. But after you are done safely refactoring, you can/should remove the tests.
Should I keep this test after the refactoring?
No!