[TFUI] Re: Is it possible to dynamically extend Test::Unit test cases?

Phlip <[email protected]> Tue, 15 Jul 2008 07:25:41 -0700
Newsgroups gmane.comp.programming.test-first-user-interfaces
Message-ID <[email protected]>
--yIyyreABSjirtwmcZFV6DwPjWCjAFPXYjPRUUk5
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

David Mitchell wrote:

> The reason I need to do this is that we've got a small Watir-based DSL
> written to allow us to drive an app through code that looks sort of
> like:
> login("fred", "password")
> click_tab("Reports")
> click_drilldown("Asia")
> open_report("Some report title")
> ..
> 
> It essentially lets us construct test cases in something like plain English.

Do your programmers run that after every edit?

> We built a few test cases using the DSL with a "normal"
> Test::Unit::TestCase approach, then showed them to our testers.
> Everyone was pretty excited about it; we can generate our own test
> data using the DSL, the testers can comprehend the DSL without having
> to dig into the nuts and bolts of the application itself, we can
> finally build a full regression test suite for an application that's
> basically a pig to drive using normal automation testing tools like
> QTP, the scripts we write using the DSL are easy to maintain over
> time, and everyone's happy.

Asking the question another way - do your developers write any tests?

> Once our testers got a look at that, they pointed out what should've
> been obvious all along: we can now get actual business users to write
> a lot of the test cases using the DSL, rather than using specialist
> testers.  Rather than writing huge business requirements documents
> that have a habit of getting misinterpreted, we can get the business
> users to create what are essentially test cases using the DSL, and
> that gives the developers a reasonably unambiguous description of how
> things are supposed to work - we'll save a whole lot of time and money
> we're currently wasting translating between business-speak and
> developer-speak.

Awesome! Now, can your business side actually run the tests - such as thru a web 
site with a "what if" interface?

> The only problem was the "scaffolding" code; apparently business users
> are incapable of writing/extending code that looks like
> 
> class Testcases < Test::Unit::TestCase
>   def test_1
>     <<DSL stuff here>>
>   end
>   def test_2
>     <<more DSL stuff here>>
>   end
>   ...
> end
> 
> but they are capable of creating a bunch of test cases in individual
> files that contain nothing but the DSL commands.  They'll use e.g.
> Notepad to create test cases in individual files that look like:
> login('fred', 'password')
> click_tab('Reports')

That sounds like Fitnesse's territory. It does the Notepad thing, but with a 
real GUI around it. Your customer team writes the test criteria in a DSL, and 
FIT acts as a test runner.

> Fine with me - I just work here...
> 
> So now I've got a situation where we're going to have business users
> generating loads of test cases using our DSL (without any of that
> nasty complicated Test::Unit::TestCase stuff), saving them in flat
> files, and we need to run be able to run some unspecified number of
> test cases that will change over time.  What I need to be able to do
> is something like:
> 
> Dir.glob("app_test_cases/**/*.app).each do |test_script_file|
>   <<grab the content of each file, build a new Test::Unit::TestCase
> wrapper around it and eval it>>
> end

Now the slight problem is you are using TestCase as your runner, when it's full 
of features you don't need, and thin on features you actually do need. More below.

> That's no problem - I've got most of this working already; all I
> needed was the way to dynamically add new test cases, and you've now
> given me a way to do that.  I'll have a play with it tomorrow.

I use define_method, in Rails, like this:

   [all this controller's actions].each do
      define_method test_one_action_#{action} do
        # test one common thing
      end
   end

The first thing you need to look for is if your failures are humane, or if they 
are a huge mass of developer-friendly diagnostics and stack traces. The great 
thing about a DSL (per RSpec) is (reputedly!) that faults can lead with clear 
English too: "The frob should have returned 42 but it returned 43".

-- 
   Phlip

--yIyyreABSjirtwmcZFV6DwPjWCjAFPXYjPRUUk5
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
</head>




<body style="background-color: #ffffff;">

<!--~-|**|PrettyHtmlStartT|**|-~-->
<div id="ygrp-mlmsg" style="width:655px; position:relative;">
<div id="ygrp-msg" style="width: 470px; margin:0; padding:0 25px 0 0; float:left; z-index:1;">
<!--~-|**|PrettyHtmlEndT|**|-~-->

    <div id="ygrp-text">
            <p>David Mitchell wrote:<br>
<br>
&gt; The reason I need to do this is that we've got a small Watir-based DSL<br>
&gt; written to allow us to drive an app through code that looks sort of<br>
&gt; like:<br>
&gt; login(&quot;fred&quot;<wbr>, &quot;password&quot;)<br>
&gt; click_tab(&quot;Reports&quot;<wbr>)<br>
&gt; click_drilldown(<wbr>&quot;Asia&quot;)<br>
&gt; open_report(<wbr>&quot;Some report title&quot;)<br>
&gt; ..<br>
&gt; <br>
&gt; It essentially lets us construct test cases in something like plain English.<br>
<br>
Do your programmers run that after every edit?<br>
<br>
&gt; We built a few test cases using the DSL with a &quot;normal&quot;<br>
&gt; Test::Unit::<wbr>TestCase approach, then showed them to our testers.<br>
&gt; Everyone was pretty excited about it; we can generate our own test<br>
&gt; data using the DSL, the testers can comprehend the DSL without having<br>
&gt; to dig into the nuts and bolts of the application itself, we can<br>
&gt; finally build a full regression test suite for an application that's<br>
&gt; basically a pig to drive using normal automation testing tools like<br>
&gt; QTP, the scripts we write using the DSL are easy to maintain over<br>
&gt; time, and everyone's happy.<br>
<br>
Asking the question another way - do your developers write any tests?<br>
<br>
&gt; Once our testers got a look at that, they pointed out what should've<br>
&gt; been obvious all along: we can now get actual business users to write<br>
&gt; a lot of the test cases using the DSL, rather than using specialist<br>
&gt; testers.  Rather than writing huge business requirements documents<br>
&gt; that have a habit of getting misinterpreted, we can get the business<br>
&gt; users to create what are essentially test cases using the DSL, and<br>
&gt; that gives the developers a reasonably unambiguous description of how<br>
&gt; things are supposed to work - we'll save a whole lot of time and money<br>
&gt; we're currently wasting translating between business-speak and<br>
&gt; developer-speak.<br>
<br>
Awesome! Now, can your business side actually run the tests - such as thru a web <br>
site with a &quot;what if&quot; interface?<br>
<br>
&gt; The only problem was the &quot;scaffolding&quot; code; apparently business users<br>
&gt; are incapable of writing/extending code that looks like<br>
&gt; <br>
&gt; class Testcases &lt; Test::Unit::<wbr>TestCase<br>
&gt;   def test_1<br>
&gt;     &lt;&lt;DSL stuff here&gt;&gt;<br>
&gt;   end<br>
&gt;   def test_2<br>
&gt;     &lt;&lt;more DSL stuff here&gt;&gt;<br>
&gt;   end<br>
&gt;   ...<br>
&gt; end<br>
&gt; <br>
&gt; but they are capable of creating a bunch of test cases in individual<br>
&gt; files that contain nothing but the DSL commands.  They'll use e.g.<br>
&gt; Notepad to create test cases in individual files that look like:<br>
&gt; login('fred'<wbr>, 'password')<br>
&gt; click_tab('Reports'<wbr>)<br>
<br>
That sounds like Fitnesse's territory. It does the Notepad thing, but with a <br>
real GUI around it. Your customer team writes the test criteria in a DSL, and <br>
FIT acts as a test runner.<br>
<br>
&gt; Fine with me - I just work here...<br>
&gt; <br>
&gt; So now I've got a situation where we're going to have business users<br>
&gt; generating loads of test cases using our DSL (without any of that<br>
&gt; nasty complicated Test::Unit::<wbr>TestCase stuff), saving them in flat<br>
&gt; files, and we need to run be able to run some unspecified number of<br>
&gt; test cases that will change over time.  What I need to be able to do<br>
&gt; is something like:<br>
&gt; <br>
&gt; Dir.glob(&quot;app_<wbr>test_cases/<wbr>**/*.app)<wbr>.each do |test_script_<wbr>file|<br>
&gt;   &lt;&lt;grab the content of each file, build a new Test::Unit::<wbr>TestCase<br>
&gt; wrapper around it and eval it&gt;&gt;<br>
&gt; end<br>
<br>
Now the slight problem is you are using TestCase as your runner, when it's full <br>
of features you don't need, and thin on features you actually do need. More below.<br>
<br>
&gt; That's no problem - I've got most of this working already; all I<br>
&gt; needed was the way to dynamically add new test cases, and you've now<br>
&gt; given me a way to do that.  I'll have a play with it tomorrow.<br>
<br>
I use define_method, in Rails, like this:<br>
<br>
[all this controller's actions].each do<br>
      define_method test_one_action_<wbr>#{action} do<br>
        # test one common thing<br>
      end<br>
   end<br>
<br>
The first thing you need to look for is if your failures are humane, or if they <br>
are a huge mass of developer-friendly diagnostics and stack traces. The great <br>
thing about a DSL (per RSpec) is (reputedly!) that faults can lead with clear <br>
English too: &quot;The frob should have returned 42 but it returned 43&quot;.<br>
<br>
-- <br>
   Phlip<br>
</p>
    </div>  

    <!--~-|**|PrettyHtmlStart|**|-~-->
    <span width="1" style="color: white;">__._,_.___</span>
    <!-- Start the section with Message In topic -->
    <div id="ygrp-actbar">
              <span class="left">
          <a href="http://groups.yahoo.com/group/TestFirstUserInterfaces/message/1013;_ylc=X3oDMTM0OGV1YmExBF9TAzk3MzU5NzE0BGdycElkAzg3NDQ3MDQEZ3Jwc3BJZAMxNzA1MDA3MjA3BG1zZ0lkAzEwMTMEc2VjA2Z0cgRzbGsDdnRwYwRzdGltZQMxMjE2MTMxOTUxBHRwY0lkAzEwMTM-">
            Messages in this topic          </a> (<span class="bld">1</span>)
        </span>
        <a href="http://groups.yahoo.com/group/TestFirstUserInterfaces/post;_ylc=X3oDMTJwbmg3aGhlBF9TAzk3MzU5NzE0BGdycElkAzg3NDQ3MDQEZ3Jwc3BJZAMxNzA1MDA3MjA3BG1zZ0lkAzEwMTMEc2VjA2Z0cgRzbGsDcnBseQRzdGltZQMxMjE2MTMxOTUx?act=reply&messageNum=1013">
          <span class="bld">
            Reply          </span> (via web post)
        </a>  | 
        <a href="http://groups.yahoo.com/group/TestFirstUserInterfaces/post;_ylc=X3oDMTJlZmZiOWJsBF9TAzk3MzU5NzE0BGdycElkAzg3NDQ3MDQEZ3Jwc3BJZAMxNzA1MDA3MjA3BHNlYwNmdHIEc2xrA250cGMEc3RpbWUDMTIxNjEzMTk1MQ--" class="bld">
          Start a new topic        </a>
          </div> 
    <!-------     Start Nav Bar  ------>
    <!-- |**|begin egp html banner|**| -->
    <div id="ygrp-vitnav">
                <a href="http://groups.yahoo.com/group/TestFirstUserInterfaces/messages;_ylc=X3oDMTJlYWwyZG1oBF9TAzk3MzU5NzE0BGdycElkAzg3NDQ3MDQEZ3Jwc3BJZAMxNzA1MDA3MjA3BHNlYwNmdHIEc2xrA21zZ3MEc3RpbWUDMTIxNjEzMTk1MQ--">Messages</a>  
            |    <a href="http://groups.yahoo.com/group/TestFirstUserInterfaces/files;_ylc=X3oDMTJmdmlnYTV0BF9TAzk3MzU5NzE0BGdycElkAzg3NDQ3MDQEZ3Jwc3BJZAMxNzA1MDA3MjA3BHNlYwNmdHIEc2xrA2ZpbGVzBHN0aW1lAzEyMTYxMzE5NTE-">Files</a>  
            |    <a href="http://groups.yahoo.com/group/TestFirstUserInterfaces/photos;_ylc=X3oDMTJlNWJrNTA1BF9TAzk3MzU5NzE0BGdycElkAzg3NDQ3MDQEZ3Jwc3BJZAMxNzA1MDA3MjA3BHNlYwNmdHIEc2xrA3Bob3QEc3RpbWUDMTIxNjEzMTk1MQ--">Photos</a>  
            |    <a href="http://groups.yahoo.com/group/TestFirstUserInterfaces/links;_ylc=X3oDMTJmZGh2ZGE0BF9TAzk3MzU5NzE0BGdycElkAzg3NDQ3MDQEZ3Jwc3BJZAMxNzA1MDA3MjA3BHNlYwNmdHIEc2xrA2xpbmtzBHN0aW1lAzEyMTYxMzE5NTE-">Links</a>  
            |    <a href="http://groups.yahoo.com/group/TestFirstUserInterfaces/database;_ylc=X3oDMTJja2tuaHJvBF9TAzk3MzU5NzE0BGdycElkAzg3NDQ3MDQEZ3Jwc3BJZAMxNzA1MDA3MjA3BHNlYwNmdHIEc2xrA2RiBHN0aW1lAzEyMTYxMzE5NTE-">Database</a>  
            |    <a href="http://groups.yahoo.com/group/TestFirstUserInterfaces/polls;_ylc=X3oDMTJmZTNybTZvBF9TAzk3MzU5NzE0BGdycElkAzg3NDQ3MDQEZ3Jwc3BJZAMxNzA1MDA3MjA3BHNlYwNmdHIEc2xrA3BvbGxzBHN0aW1lAzEyMTYxMzE5NTE-">Polls</a>  
            |    <a href="http://groups.yahoo.com/group/TestFirstUserInterfaces/members;_ylc=X3oDMTJlN2hoc2RuBF9TAzk3MzU5NzE0BGdycElkAzg3NDQ3MDQEZ3Jwc3BJZAMxNzA1MDA3MjA3BHNlYwNmdHIEc2xrA21icnMEc3RpbWUDMTIxNjEzMTk1MQ--">Members</a>  
            |    <a href="http://groups.yahoo.com/group/TestFirstUserInterfaces/calendar;_ylc=X3oDMTJkdWl1cm1mBF9TAzk3MzU5NzE0BGdycElkAzg3NDQ3MDQEZ3Jwc3BJZAMxNzA1MDA3MjA3BHNlYwNmdHIEc2xrA2NhbARzdGltZQMxMjE2MTMxOTUx">Calendar</a>  
    </div>  
    <!-- |**|end egp html banner|**| -->

                        <div id="ygrp-grft">
          

        </div>
      
                  <div id="ygrp-mkp">
      <div id="hd">MARKETPLACE</div>
      <div id="ads">
                  <div class="ad">
            <hr size=1 noshade><a href="http://us.ard.yahoo.com/SIG=13rq9ah0m/M=624381.12730922.13032918.10835568/D=groups/S=1705007207:MKP1/Y=YAHOO/EXP=1216139152/L=/B=L4qlBkLaX9A-/J=1216131952253473/A=5396693/R=0/SIG=14ete9fpo/*http://media.adrevolver.com/adrevolver/href?banner=197793&place=26143&url_=http://tc.deals.yahoo.com/tc/blockbuster/display.com?cid=bbi00027
"> Yahoo! Groups users, </a> take advantage of a<a href="http://us.ard.yahoo.com/SIG=13rq9ah0m/M=624381.12730922.13032918.10835568/D=groups/S=1705007207:MKP1/Y=YAHOO/EXP=1216139152/L=/B=L4qlBkLaX9A-/J=1216131952253473/A=5396693/R=1/SIG=14ete9fpo/*http://media.adrevolver.com/adrevolver/href?banner=197793&place=26143&url_=http://tc.deals.yahoo.com/tc/blockbuster/display.com?cid=bbi00027
"> free trial offer from Blockbuster!</a>          </div>
                              </div>
    </div>
      
    <!-- yahoo logo -->
    <!-- |**|begin egp html banner|**| -->
    <div id="ygrp-ft">
      <a href="http://groups.yahoo.com/;_ylc=X3oDMTJkaDh2bDJnBF9TAzk3MzU5NzE0BGdycElkAzg3NDQ3MDQEZ3Jwc3BJZAMxNzA1MDA3MjA3BHNlYwNmdHIEc2xrA2dmcARzdGltZQMxMjE2MTMxOTUx">
      <img src="http://us.i1.yimg.com/us.yimg.com/i/yg/img/logo/ma_grp_160.gif" height="15" width="106" border="0" alt="Yahoo! Groups"></a> <br>
      <a href="http://groups.yahoo.com/group/TestFirstUserInterfaces/join;_ylc=X3oDMTJmY2N0cmhuBF9TAzk3MzU5NzE0BGdycElkAzg3NDQ3MDQEZ3Jwc3BJZAMxNzA1MDA3MjA3BHNlYwNmdHIEc2xrA3N0bmdzBHN0aW1lAzEyMTYxMzE5NTE-">Change settings via the Web</a> (Yahoo! ID required) <br>
      Change settings via email: <a href="mailto:TestFirstUserInterfaces-digest-hHKSG33TihhbjbujkaE4pw@public.gmane.org?subject=Email Delivery: Digest">Switch delivery to Daily Digest</a> | <a href = "mailto:TestFirstUserInterfaces-traditional-hHKSG33TihhbjbujkaE4pw@public.gmane.org?subject=Change Delivery Format: Traditional">Switch format to Traditional</a> <br>

      <a href="http://groups.yahoo.com/group/TestFirstUserInterfaces;_ylc=X3oDMTJkaTJjYnAyBF9TAzk3MzU5NzE0BGdycElkAzg3NDQ3MDQEZ3Jwc3BJZAMxNzA1MDA3MjA3BHNlYwNmdHIEc2xrA2hwZgRzdGltZQMxMjE2MTMxOTUx">
        Visit Your Group 
      </a> |
      <a href="http://docs.yahoo.com/info/terms/">
        Yahoo! Groups Terms of Use      </a> |
      <a href="mailto:TestFirstUserInterfaces-unsubscribe-hHKSG33TihhbjbujkaE4pw@public.gmane.org?subject=">
        Unsubscribe      </a> 
    </div>     <!-- |**|end egp html banner|**| -->
  </div> <!-- ygrp-msg -->

  
  <!-- Sponsor -->
  <!-- |**|begin egp html banner|**| -->
  <div id="ygrp-sponsor" style="width:160px; float:right; clear:none; margin:0 0 25px 0; background:white;">
    <!-- Network content -->
    
<!-- Start Recommendations -->
<div id="ygrp-reco">
     </div>
<!-- End Recommendations -->

	    <!-- Start vitality -->
	    <div id="ygrp-vital">
	      	      <a href="http://groups.yahoo.com/group/TestFirstUserInterfaces;_ylc=X3oDMTJlaWZwa2dhBF9TAzk3MzU5NzE0BGdycElkAzg3NDQ3MDQEZ3Jwc3BJZAMxNzA1MDA3MjA3BHNlYwN2dGwEc2xrA3ZnaHAEc3RpbWUDMTIxNjEzMTk1MQ--">
		Visit Your Group	      </a>
	    </div> 
	    	    	      
	    <!-- Network content -->
	    	          <div id="nc">
              <div class="ad">
                      <div id="hd1">Yahoo! Finance</div> 
<p><a href="http://us.ard.yahoo.com/SIG=13ovgdvg1/M=493064.12016257.12445664.8674578/D=groups/S=1705007207:NC/Y=YAHOO/EXP=1216139152/L=/B=MIqlBkLaX9A-/J=1216131952253473/A=4507179/R=0/SIG=12de4rskk/*http://us.rd.yahoo.com/evt=50284/*http://finance.yahoo.com/personal-finance">It's Now Personal</a></p> 
<p>Guides, news,</p> 
<p>advice & more.</p>                   </div>
                    <div class="ad">
                      <div id="hd1">New web site?</div> 
<p><a href="http://us.ard.yahoo.com/SIG=13out904m/M=493064.12016308.12445700.8674578/D=groups/S=1705007207:NC/Y=YAHOO/EXP=1216139152/L=/B=MYqlBkLaX9A-/J=1216131952253473/A=3848642/R=0/SIG=131eshi2t/*http://searchmarketing.yahoo.com/arp/srchv2.php?o=US2004&cmp=Yahoo&ctv=Groups3&s=Y&s2=&s3=&b=50">Drive traffic now.</a></p> 
<p>Get your business</p> 
<p>on Yahoo! search.</p>                  </div>
                    <div class="ad">
                      <div id="hd1">10 Day Club</div> 
<p><a href="http://us.ard.yahoo.com/SIG=13op6sfdh/M=493064.12016283.12445687.8674578/D=groups/S=1705007207:NC/Y=YAHOO/EXP=1216139152/L=/B=MoqlBkLaX9A-/J=1216131952253473/A=5202316/R=0/SIG=11aijbghb/*http://new.groups.yahoo.com/allbrangroup">on Yahoo! Groups</a></p> 
<p>Share the benefits</p> 
<p>of a high fiber diet.</p>                  </div>
          </div>
	    
	  </div> 	  <!-- |**|end egp html banner|**| -->
	  <div style="clear:both; color: #FFF; font-size:1px;">.</div>
	</div> 		  <img src="http://geo.yahoo.com/serv?s=97359714/grpId=8744704/grpspId=1705007207/msgId=1013/stime=1216131951/nc1=4507179/nc2=3848642/nc3=5202316" width="1" height="1"> <br>
	
	<span  style="color: white;">__,_._,___</span>
	<!--~-|**|PrettyHtmlEnd|**|-~-->
	</body>
	<!--~-|**|PrettyHtmlStart|**|-~-->
	<head>
<style type="text/css">
<!--
#ygrp-mkp{
  border: 1px solid #d8d8d8;
  font-family: Arial;
  margin: 14px 0px;
  padding: 0px 14px;
}
#ygrp-mkp hr{
  border: 1px solid #d8d8d8;
}
#ygrp-mkp #hd{
  color: #628c2a;
  font-size: 85%;
  font-weight: bold;
  line-height: 122%;
  margin: 10px 0px;
}
#ygrp-mkp #ads{
  margin-bottom: 10px;
}
#ygrp-mkp .ad{
  padding: 0 0;
}
#ygrp-mkp .ad a{
  color: #0000ff;
  text-decoration: none;
}
-->
</style>
</head>
	<head>
<style type="text/css">
<!--
#ygrp-sponsor #ygrp-lc{
  font-family: Arial;
}
#ygrp-sponsor #ygrp-lc #hd{
  margin: 10px 0px;
  font-weight: bold;
  font-size: 78%;
  line-height: 122%;
}
#ygrp-sponsor #ygrp-lc .ad{
  margin-bottom: 10px;
  padding: 0 0;
}
-->
</style>
</head>
	<head>
	<style type="text/css">
	<!--
	#ygrp-mlmsg {font-size:13px; font-family: arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}
	#ygrp-mlmsg table {font-size:inherit;font:100%;}
	#ygrp-mlmsg select, input, textarea {font:99% arial,helvetica,clean,sans-serif;}
	#ygrp-mlmsg pre, code {font:115% monospace;*font-size:100%;}
	#ygrp-mlmsg * {line-height:1.22em;}
	#ygrp-text{
	    font-family: Georgia;	
	}
	#ygrp-text p{
	    margin: 0 0 1em 0;
	}
	#ygrp-tpmsgs{
	    font-family: Arial;	
	    clear: both;
	}
	#ygrp-vitnav{
		padding-top: 10px;
		font-family: Verdana;
		font-size: 77%;
		margin: 0;
	}
	#ygrp-vitnav a{
		padding: 0 1px;
	}
	#ygrp-actbar{
		clear: both;
		margin: 25px 0;
		white-space:nowrap;
		color: #666;
		text-align: right;
	}
	#ygrp-actbar .left{
		float: left;
		white-space:nowrap;
	}
	.bld{font-weight:bold;}
	#ygrp-grft{
		font-family: Verdana;
		font-size: 77%;
		padding: 15px 0;
	}
	#ygrp-ft{
	  font-family: verdana;
	  font-size: 77%;
	  border-top: 1px solid #666; 
	  padding: 5px 0; 
	}
	#ygrp-mlmsg #logo{
	  padding-bottom: 10px;
	}

	#ygrp-reco {
	margin-bottom: 20px;
	padding: 0px;
	}
	#ygrp-reco #reco-head {
		font-weight: bold;
		color: #ff7900;
	}

	#reco-grpname{
        font-weight: bold;
        margin-top: 10px;
  	}
	#reco-category{
        	font-size: 77%;
	}
	#reco-desc{
        	font-size: 77%;
	}

	#ygrp-vital{
		background-color: #e0ecee;
		margin-bottom: 20px;
		padding: 2px 0 8px 8px;
	}
	#ygrp-vital #vithd{
		font-size: 77%;
		font-family: Verdana;
		font-weight: bold;
		color: #333;
		text-transform: uppercase;
	}
	#ygrp-vital ul{
		padding: 0;
		margin: 2px 0;
	}
	#ygrp-vital ul li{
	  list-style-type: none;
	  clear: both;
	  border: 1px solid #e0ecee;  
	}
	#ygrp-vital ul li .ct{
	  font-weight: bold;
	  color: #ff7900;
	  float: right;
	  width: 2em;
	  text-align:right;
	  padding-right: .5em;
	}
	#ygrp-vital ul li .cat{
	  font-weight: bold;
	}
	#ygrp-vital a{
		text-decoration: none;
	}

	#ygrp-vital a:hover{
	  text-decoration: underline;
	}

	#ygrp-sponsor #hd{
		color: #999;
		font-size: 77%;
	}
	#ygrp-sponsor #ov{
		padding: 6px 13px;
		background-color: #e0ecee;
		margin-bottom: 20px;
	}
	#ygrp-sponsor #ov ul{
		padding: 0 0 0 8px;
		margin: 0;
	}
	#ygrp-sponsor #ov li{
		list-style-type: square;
		padding: 6px 0;
		font-size: 77%;
	}
	#ygrp-sponsor #ov li a{
		text-decoration: none;
		font-size: 130%;
	}
	#ygrp-sponsor #nc{
	  background-color: #eee;
	  margin-bottom: 20px;
	  padding: 0 8px;
	}
	#ygrp-sponsor .ad{
		padding: 8px 0;
	}
	#ygrp-sponsor .ad #hd1{
		font-family: Arial;
		font-weight: bold;
		color: #628c2a;
		font-size: 100%;
		line-height: 122%;
	}
	#ygrp-sponsor .ad a{
		text-decoration: none;
	}
	#ygrp-sponsor .ad a:hover{
		text-decoration: underline;
	}
	#ygrp-sponsor .ad p{
		margin: 0;
	}
	o{font-size: 0; }
	.MsoNormal{
	   margin: 0 0 0 0;
	}
	#ygrp-text tt{
	  font-size: 120%;
	}
	blockquote{margin: 0 0 0 4px;}
	.replbq{margin:4}
	-->
	</style>
	</head>
	<!--~-|**|PrettyHtmlEnd|**|-~-->
	</html><!--End group email -->


--yIyyreABSjirtwmcZFV6DwPjWCjAFPXYjPRUUk5--