Page 1 of 1

Writing complex "helper" methods into testcases?

Posted: Mon Mar 05, 2007 12:20 am
by Chris Corbyn
I'm at a point where I think I need to seriously refactor a few of my testcases because they repeatedly use long, complicated regexes like this:

Code: Select all

public function testDetachingALLPartsFromAnEmailWithAnAttachmentResultsInCorrectStructure()
	{
		$msg = new Swift_Message();
		$id1 = $msg->attach(new Swift_Message_Part("some part"));
		$id2 = $msg->attach(new Swift_Message_Part("another part"));
		$id3 = $msg->attach(new Swift_Message_Attachment("foobar"));
		$id4 = $msg->attach(new Swift_Message_Attachment("zipbutton"));
		
		$msg->detach($id2);
		$structure = $msg->build()->readFull();
		//$this->dump($structure);
		$this->assertPattern(
			"~.*?Content-Type: multipart/mixed;\\s* boundary=(\"?)(.*?)\\1\r\n" .
			".*?\r\n\r\n" .
			".*?\r\n--\\2\r\n" .
			"Content-Type: multipart/alternative;\\s* boundary=(\"?)(.*?)\\3\r\n" .
			".*?\r\n\r\n" .
			".*?\r\n--\\4\r\n" .
			".*?\r\n\r\n" .
			".*?\r\n--\\4--" .
			"\\s*\r\n--\\2\r\n" .
			".*?\r\n\r\n" .
			".*?\r\n--\\2\r\n" .
			".*?\r\n\r\n" .
			".*?\r\n--\\2--~s",
			$structure);
		
		$msg->detach($id1);
		$structure = $msg->build()->readFull();
		//$this->dump($structure);
		$this->assertNoPattern("~Content-Type: multipart/alternative~", $structure);
		$this->assertNoPattern(
			"~.*?Content-Type: multipart/mixed;\\s* boundary=(\"?)(.*?)\\1\r\n" .
			".*?\r\n\r\n" .
			".*?\r\n--\\2\r\n" .
			"Content-Type: multipart/alternative;.*?\r\n" .
			".*?\r\n\r\n" .
			".*?\r\n--\\2\r\n" .
			".*?\r\n\r\n" .
			".*?\r\n--\\2--~s",
			$structure);
	}
The regex are:

a) A vital annoyance to test what I need
b) COMPLICATED!!

I'd like to simplify, and make the tests more readable to "Average Joe" by allowing something like XML or a native multi-dimensional array to generate those regex, but that's complicated in itself so I'd then need to add a handful of methods which tests the helper functions of my test case before I ever use the helper functions. Does this seem reasonable or am I just adding to the risk of over-complicating things?

I haven't even begun to pull hairs out thinking about actually creating those regex in a flexible fashion 8O

Posted: Mon Mar 05, 2007 4:53 am
by Jenk
I think that even though it is a lot, it is the "simplest" way to test. You are providing test data, and asking for test results.

If you start to build dynamics into your tests, you'll need to test your object/function which creates the dynamic content. Kind of like the dependency tree which you break with mock's, only this time you break with static data. :)

Posted: Mon Mar 05, 2007 9:13 am
by Maugrim_The_Reaper
I think the rock is better than the hard place ;).

Are the regex's going to change in the future? If not, there's little point messing with them since they are specific to a test case. Now, that method name on the other hand...
testDetachingALLPartsFromAnEmailWithAnAttachmentResultsInCorrectStructure()
:P

Posted: Mon Mar 05, 2007 9:28 am
by Chris Corbyn
Maugrim_The_Reaper wrote:I think the rock is better than the hard place ;).

Are the regex's going to change in the future? If not, there's little point messing with them since they are specific to a test case. Now, that method name on the other hand...
testDetachingALLPartsFromAnEmailWithAnAttachmentResultsInCorrectStructure()
:P
"CorrectStructure" needs describing a little better. I think it should be:

Code: Select all

public function testDetachingAllAlternativePartsFromAMultipartMixedAndAlternativeEmailYieldsNoMultipartAlternativePartInBody()
{
    //
}

Posted: Mon Mar 05, 2007 10:04 am
by Jenk
Can you not split that test up? I realise you are testing a whole email (thus one test) with 'x', 'y' and 'z' but would it be better to test 'x', 'y' and 'z' seperately? A group maybe?

Posted: Thu Mar 22, 2007 6:17 pm
by dreamscape
d11wtq wrote:

Code: Select all

public function testDetachingAllAlternativePartsFromAMultipartMixedAndAlternativeEmailYieldsNoMultipartAlternativePartInBody()
{
    //
}
Good grief charley brown... 8O .. yuk... :D

I like to group test cases by context, so maybe:

Code: Select all

class A_Multipart_Mixed_And_Alternative_Email extends Test_Case
{
	public function test_Detaching_All_Alternative_Parts_Yields_No_Multipart_Alternative_Part_In_Body()
	{
	}	
}
And actually that test would be changing context in the middle of the test, so even better would be:

Code: Select all

class A_Multipart_Mixed_And_Alternative_Email_With_All_Alternative_Parts_Detatched extends Test_Case
{
	public function test_Has_No_Multipart_Alternative_Part_In_Body()
	{	
	}
}
Much easier to digest... JIMHO :wink:

Posted: Thu Mar 22, 2007 6:47 pm
by Chris Corbyn
True :) I've never tried it, but I assume simpletest can run Group tests inside group tests.

I'm actually going to go through my tests this weekend and refactor/tidy up a bit, possibly even add descriptive comments to the files for some if the scarier tests.