Sunday, July 3, 2011

Testing Asp.Net pages

Update - Arlo Belshee pointed out this applies better to "older" style asp programming.  If your pages don't resemble this pattern, please check out his response 

[Video at bottom of page]
Here is the strategy I’ve been using for unit testing Asp.Net pages. Aspx pages were almost intentionally made to be hard to test, so the result is as elegant as is possible for the given situation.

Note: If you want to test something that isn’t the “end result” of a web page, simply pull that logic into a separate class\method\dll and test it normally. This is for testing the final output of the page.


The Bottom Line: The following 1 line will test the AspxClass for a given scenario.

Approvals.ApproveAspPage(new AspxClass().TestMethod)

Architecture:

The Normal architecture when testing web pages is as follows


The strategy I've developed is very simular to this, but allows for better "test functionality" by adding a test method IN the aspx page, and then allowing a secret handshake, or backdoor to the aspx page to run that scenario.

Most Unit Tests for an asp.net page will take this form
1) Create an aspx page
2) Do some scenario
3) Verify the output of the page

When you do this in your testing, those 3 steps are going to  be split out across your code into 3 separate places:
1) The PageLoad event of your aspx page will handle the creation of the page and the redirect to the scenario of your choice (the TestMethod).
2) There will be a TestMethod which does the scenario part IN your aspx code behind page.
3) The Unit Test will Callout to the aspx page and verify the html output from the page. This actually starts the whole thing.

Simple Example:

Let’s say I wanted to test how an aspx page renders for a given company invoice:

Step 1) Write the Unit Test verification IN the Unit Test Class

Approvals.ApproveAspPage(new CompanyInvoiceView().TestSimpleInvoice);

it’s important to note that I’m not calling the method “TestSimpleInvoice” this is just a Delegate to that method. This is so I can “reflect” the http call needed to run the test.

Step 2) Write the Unit Test Setup IN the aspx page

public void TestSimpleInvoice()
{
    invoice = new Invoice{Name = “Test Company”}
    invoice.AddLineItem(“candy bar”, count = 2, cost = 0.50);
    invoice.AddLineItem(“soda”, count = 1, cost = 1.50);
    invoice.TaxRate = 0.10;
}


Step 3) Adding the “Test Diverter” IN the aspx page

Next, we need to intercept the call to go to the Test Method. This means adding the following code at the beginning of the Page_Load event

protected void Page_Load(object sender, EventArgs e)
{
    if (AspTestingUtils.DivertTestCall(this))
    {
        return;
    }


....
}


Step 4) Turn on the local test server and then run the tests.

Here’s a video of the whole thing in action...

Friday, April 22, 2011

Illusions of Grandeur and Agreement

I just finished watching Adam Savage presenting at maker faire.  It’s a pretty great talk. Kinda. 


Here’s what I’m taking away:
“Set deadlines for personal projects”


But about 22 minutes in I become pretty dissatisfied, and I want to talk about why:
 I am agreeing with Adam about everything.

Everything? Yep, It ALL makes sense. I know it ALL already... Now do I believe that if I was to sit down and actually do something with Adam that everything would be great? No disagreement? Nothing to learn? 
Of course not. That’s a stupid idea. There would be tons to learn probably in the first 22 minutes. So why am I “sitting down with him now” and not disagreeing? I think my girlfriend, Lynn Langit  who happens to be a Microsoft Evanglist, said it best today:

“Evangelist seek to make everyone in the room feel smart,
 Trainers try to make everyone in the room be smarter”

This illusion of agreement is starting to bug me more and more. I don’t want to spend and hour feeling smart. I want to be smarter, but I think I’m a bit odd in this. Odd not just in the desire to learn, but in my reaction when I am, or am not, learning.

There is an interesting video from Veritasium about this.
Learning involves some disagreement. So next time you are watching someone talk, ask yourself “Am I agreeing with everything?”  If you are there is probably a miscommunication going on. 

I am constantly reminded of the training scene from ‘The Matrix’:

Morpheus: How did I beat you? 
Neo: (breathing hard) You... you're too fast. 
Morpheus: Do you believe that my being stronger or faster has anything to do with my muscles in this place? 
Neo: (Shakes Head No)
Morpheus: Do you think that's air you're breathing now?
Neo: (Stops breathing hard)

Saturday, January 8, 2011

Lambdas v.008, usable Now! Forward compatible with Java 1.7

I released Java Lambdas v.008 which allows for forward compatibility with the new Lambda implementation coming down the pike for Java 7

The idea is this. Create methods that receive a Function[0-9] or Action[0-9], and then create that lambda with either my current lambda implementation F[0-9] or A[0-9] now, or when Java 7 finally implements lambdas in the syntax, simply convert them to that official syntax #{a->a}

Let's look at an example:
Get all the people over 35 years old
To do this, we want to use the method

Query.where(List, Function1<T, Boolean>)


S1 implements Function1, so we can write the following in Java 6

 List<Person> people =
      Query.where(getStudents(), new S1<Person>(a){{ret(a.getAge() > 35);}});


However, once Java 7 releases the official Lambdas, we can convert this to the much simpler call


List<Person> people = 
      Query.where(getStudents(),#{a -> a.getAge() > 35});



Because Function1 is a SAM interface (single abstract method)


Why Use Lambdas?
Hopefully this will make it easier to start using lambdas in your production code. Lambdas(Closures) are all about using the open/closed principal . They are a bit tricky to use at 1st. But soon they will become essential to you. I think of them as the next step in subroutines. 

In simpler languages, you could create a subroutine, but not pass variables in. If you wanted to have a function 

People.whereMimimumAgeIs21()

you could, but you could not have 

People.where(int MimimumAge ) 
and call
People.where(21)

Parameters allowed you to reduce duplication by saying "this variable can be different for each call".
Lambdas do the same thing, but with duplicate code. Now you can say

People.where(Function1 whereClause ) 
and call
People.where(#{p -> p.age > 21})

Note: For the record, I dislike the currently proposed (1/8/2011) Java 1.7 lambda syntax, and vastly prefer the C# syntax
People.where(p => p.age > 21)

Links:



Tuesday, December 7, 2010

Complete Unit Testing

Today I had a conversation with @WoodZuill where an extremely rare situation came up. A situation where you can practice TDD with Completeness of the possible user scenarios.

I vBlogged my thoughts here:



I'm using the LegacyApprovals package (which I wrote, download below)  here to test every combination of the possible parameters.

It's worth pointing out this is NOT what the LegacyApprovals package was actually made for. It's design to test a lot of cases, but not every case.

Links:
Approval Tests (Legacy Approvals is part of the standard ApprovalTest download.)
Note: In C# it's ApprovalTests.Combinations.Approvals.ApproveAllCombinations()
        In Java it's org.approvaltests.legacycode.LegacyApprovals.approve()

More Agile Thoughts

Tuesday, October 12, 2010

Java Lambdas

I mentioned last month that I had found a way to add lambdas to the current JDK. I struck me that perhaps many of you had not used lambdas before, so I thought I make a small tutorial on one of the common uses:

Sql like queries against your objects.
Let’s start with the most basic,

Order By
If you where writing an Sql query to get people based on age, you would say

Select *
From People 
Order By age

or perhaps

Select *
From People a
Order By a.age

If you had an array of people in C# this would be written as 

Linq.OrderBy(people, a => a.GetAge())

Now, to do this in Java is a little more compacted, but very similar

Query.orderBy(people, new S1<Person>(a){{ret(a.getAge());}});

let’s look at some more examples.

Select
Let’s say you wanted to get the names of all the people, you’d write a query like

Select a.names
From people a

Now, let’s translate that into java

Query.select(people, new F1<Person, String>(a){{ret(a.getName());}});

of course, with java you can select more than just primitives, if you wanted the Addresses, you could do that too.

 Query.select(people, new F1<Person, Address>(a){{ret(a.getAddress());}});

you can even do transforms

 List<Student> students = 
     Query.select(people, 
        new F1<Person, Student>(a){{ret(new Student(a.getName(), a.getAge()));}});



let’s move on.

Where
Of course most queries wouldn’t be much use without the where statement. Let’s find the all the A+ students

Query.where(people, new F1<Person,Boolean>(a){{ret(a.getGradePoint() > 3.8);}})

btw: it might be worth expanding the code a bit. I’m cheating a little to help with understanding. For lambdas to work in Java, there is an unfortunate side effect. It gets call 1 extra time. Specifically the first time. So you need to pass in an object. That object  in the examples above is pre-defined as ‘a’ but in practice I usually use a blank object

new F1<Person,Boolean>(new Person()){{ret(a.getGradePoint() > 3.8);}}

unfortunately, you can’t use ‘null’ because it would throw a null pointer exception. I also use the null object pattern a lot: Person.Null
of course there are some standard calculations that are nice too.


Average
what if you wanted the average length of a person’s name?
simple
Query.average(people, new F1<Person, Number>(a){{ret(a.getName().length());}});

of course for averages, the return type F1<InputType, ReturnType>  must be a Number.

Min
by now you probably see how easy it would be to get a minimum or maximum, so let’s up the lambda by using a local variable. Let’s find the person who got the closest grade to sally.

 final Person sally = getPersonByName("Sally");
 Query.min(people, new S1<Person>(a, sally){{
                    ret(Math.abs(a.getGradePoint() - sally.getGradePoint()));}});



You might have noticed the final key word, java requires that for locals to be used inside of the lambdas. you might also have noticed that this time I had to pass in 2 parameters (a, sally) to use sally inside you need to add her as a parameter as well. Lastly, I used the class S1<Input> here instead of F1<Input, ReturnType> this is just a convenience class which extends F1, since any where, min, or max queries require the output to be a  Comparable object, like Integer, String etc.



Well, I hope this got you interested in what lambdas can do for you. Check out the video and download the jar to get started at http://bit.ly/lambdas

Happy coding,
Llewellyn Falco

Monday, August 30, 2010

AssertNotNull

Recently had some issues with the method assertNotNull(object) because it doesn't help with any of the 4 principles of TDD.


  1. Specifications
  2. Feedback
  3. Regression
  4. Granularity


 I vloged my thoughts here.



Finally, here's the code I was looking at.
and check out www.approvaltests.com

Saturday, September 12, 2009

Hello JRack

Today Woody Zuill and myself put some of the finishing touches on a port of Rack to Java, and published it to the world. So let's do a quick show-and-tell to show you why we are so excited.

JRack is an extremely simple yet extremely useful and powerful way to create web apps.

Simple To Create
Let's look at how simple it is to create a "Hello World" web page.
public class HelloWorldRack implements JRack
{
public RackResponse call(Map<String, Object> input)
{
return RackResponseUtils.standardHtml("HelloWorld");
}
}



Wasn't that simple? Just 1 line to pass back the html we want displayed.

Simple To Run

Of course, this has just created it. What if we actually want to have this running on a Web Server, what would we have to do?

We can simply harness it through Jetty (you can also deploy on regular servers like tomcat). Jetty is a simple, standalone Web Servlet container. You can find out more about it here:

We'll add a main method to our HelloWorldRack:
public class HelloWorldRack implements JRack
{
...
public static void main(String[] args)
{
JettyUtils.startJettyRack(80, new HelloWorldRack());
}
}
Now, if we run HelloWorldRack, we will have a fully running rack server serving the HelloWorld page.
Nice and simple. You are up and running with just two lines of code.


Simple To Test & Reuse
But what if you unit test this code? Don't you need a webserver to even run it? NO!
You can call the RackApp directly. Simply pass in what in used by the environment (in this case, nothing). Whats more we've added approval test support so you can simple approve the resulting html.


Put this code into a JUnit test class:
public void testHelloWorld() throws Exception
{
Approvals.approve(new HelloWorldRack().call(null));
}
Okay - simple to write, simple to run, simply to test. There are many sites extolling the virtues of Rack. More and more, the Ruby community is migrating over to it. And now, you can have the same simplicity in the Java world. We'll write more about it later. You can download it here.
I also encourage you to look at the test examples here