Recently in Quality Assurance Category

Powershell makes doing math on Date object easier than falling down!

 

   1: $time = Get-Date;
   2: 
   3: ##Show Minutes
   4: $time.Minutes;
   5: 
   6: ##Show Day
   7: $time.Day;
   8: 
   9: ##Find out NOW stuff
  10: (Get-Date).Day;
  11: (Get-Date).Millisecond;
  12:  
  13: ##What Will the Date be 90 days from now?
  14: (Get-Date).AddDays(90);
  15: 
  16: ##What was the day 90 days ago?
  17: (Get-Date).AddDays(-90);
  18: 
  19: ## And for something practical
  20: $startTime = Get-Date;
  21: $endTime = Get-Date;
  22: "DONE in less than " + ($endTime.AddMinutes(1) - $startTime).Minutes + " Minutes";

 

As you can see, wonderfully simple.

Technorati Tags: ,,,,,,,,,
Windows Live Tags: PowerShell,Date,Math,Minutes,Find,Millisecond,AddDays,AddMinutes,startTime,endTime

We all know that a good user story (in the agile world) contains

  • Enough facts to give the delivery team (Dev , QA, DBAs, Operations, etc.) a direction
  • Enough proper estimation to allow the product owner to know when he might expect delivery of the story
  • Enough detail to know when the team has completed the story.

We should all be familiar with the “As a [role], I can [feature] so that [reason]” format of writing a story (quote swiped from codesqueeze.com).  And we should all be familiar with Ron Jeffries’ 3 C’s (Card, conversation, and confirmation).  The thing that gets lost most often, I think is that second C. 

So I have two anecdotes for you to demonstrate the value of “conversation”.  (I’d call them stories, but that would just get confusing).  For the purposes of these anecdotes, the delivery team is represented by the store clerk and the product owner/manager is represented by the customer.

Anecdote #1:10058pf_hero

Joe Customer goes into the EverythingMart where they sell absolutely everything (as the name implies) and finds Steve Storeclerk. 

“Hey there Steve!  I’m back again and I need something from you!”

“Sure,” Steve replies, “How can I help?”

Joe Customer rubs the back of his neck with a well worn handkerchief and says, “Well, I need to haul some stuff, so I need to buy a truck from you!”

Steve’s enthusiastic to help so he pulls up the catalog of trucks on his terminal, “Perfect, we’re getting some new ones in a couple weeks!  Why don’t we sit down and take a look at what will work for you.”

“Two weeks, eh?” Mr. Customer asks, “Well, alright, I suppose so. Let’s see what you’ve got.”

The pair of them look through the catalog and pick out a blue one with chrome bumpers, GPS, and a gun rack (they live in TX and it’s a free option, so why not?).

A week Joe Customer comes in with his check for $30,000 and drives his truck home and does his hauling.  Everyone seems happy.

 

Now, as a “Story” we could write this on a card as …

“As a customer, I can haul heavy things, so that I don’t kill my back.”

Seems to meet all the criteria for a good story, right?

 

Anecdote #2:

Joe Customer goes into the EverythingMart where they sell absolutely everything (as the name implies) and finds Steve Storeclerk.

“Hey there Steve! I’m back again and I need something from you!”

“Sure,” Steve replies, “How can I help?”

Joe Customer rubs the back of his neck with a well worn handkerchief and says, “Well, I need to haul some stuff, so I need to buy a truck from you!”

“Of course, I’m sure I can help you out.  What exactly do you need to haul?” Steve asked.

“Ummm…  I’ve got some bricks that I need to bring over to my neighbor’s house to help him build a barbecue.”

Steve nods sagely and asks, “Right… And how far do you gotta haul these bricks?”

“Just two houses down,” he’s told.

Steve then logs onto his workstation and starts to browse around looking at gardening implements.  “I think one of these wheel-barrows will do just fine.  And we have them in stock right now.”

j0430445Joe Customer’s eyebrows arch inquisitively. “So,” he asks, “you don’t think that I need a truck, but this wheel-barrow will do?”

“Absolutely!” Steve tells him.  “And this will save you a bundle!”

Joe nods, whips out his credit card and pays $50 for a brand new shiny wheel-barrow.  Sure, it’s going to take him two trips to get all the bricks moved, but he’s still going to be finished by the end of the day.

 

Now as a “Story” we could write this on a card as …

“As a customer, I can haul a load of bricks to my neighbor’s house, so that I don’t kill my back.”

Sure, the first story seemed well defined, the customer told Steve exactly what he wanted and got what he wanted, albeit at a pretty heavy cost in terms of $ and time.

In the second story, though, with conversation Joe Customer got what he needed immediately and at a substantially lessened financial burden.

 

We should never assume that the customer knows exactly what they need.  Instead of dictating a solution, conversation allows us to solve the need.

To paraphrase a Rolling Stones song…

“You can’t always get what you want (at a decent cost). But if you have a conversation, you just might find, you get what you need.”

 

Technorati Tags: ,,,

.....::::: UPDATE :::::.....

Cedric Beust (the guy who wrote the book on TestNG) added a comment with a way to run single tests much much easier.  Go check out the comment below.  I'm going to leave this article up, though, I think that people might find the examples of parameters and groups might still prove useful.

----------------------------------

It's a typical story.  You have all of your tests written up with Selenium and everything is working beautifully.  Then you discover the beauty of TestNG's ability to run the tests in parallel. By adding some parameters to the XML, you are able to run multiple copies of the same tests on different browsers and operating systems. The clouds part, the angels sing on high, and you find your boss showering you with praise for cutting the total run time from four hours down to fifteen minutes.

But all is not as good as you thought.  Those blasted developers decided to change something on the page and one of your two hundred thirty-four tests is now broken. So, you dutifully open Eclipse and begin the repair work.  You finish adjusting your assertions, right-click on your test method and choose to "run as TestNG test."

Despair!  Anguish!! Gnashing of teeth!!! I don't want to run my entire class of tests just to debug a single test!!

"What the hell does that mean?"  you ask as you stare at the console output, which tells you ...

 

org.testng.TestNGException:
Parameter 'browser' is required by @Configuration on method setUp
but has not been marked @Optional or defined in C:\<MyUserDir>\AppData\Local\Temp\testng-eclipse--1466657283\testng-customsuite.xml
    at org.testng.internal.Parameters.createParameters(Parameters.java:144)
    at org.testng.internal.Parameters.createParameters(Parameters.java:327) ...

 

Apparently, when you attempt to run a single test, you are never asked to point Eclipse at the XML file you wanted to use.  Eclipse and TestNG create a nice temporary one just for the occasion.  Unfortunately, there is no way to tell the IDE where to get any XML information from.

After much cursing, scouring Google, and complaining to my co-workers, I have devised a method that allows me to run any single test (or combination of tests) without having to run the entire class' list of tests.

Here's how ...

Create an XML file for your own debugging purposes. 
You probably want to use all of your typical parameters like browser type, location of the Selenium Server/Grid Hub that you want to use, etc.

   1:  <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
   2:   
   3:  <suite name="MyTests" verbose="-1" parallel="tests" thread-count="1">
   4:        
   5:        <parameter name="seleniumGridIp" value="localhost"/>
   6:        <parameter name="seleniumGridPort" value="4444"/>
   7:        <parameter name="testServer" value="http://myServer.domain.com:8080"/>
   8:        <parameter name="debugLevel" value="1"/>
   9:        <parameter name="dbEnvironment" value="dev"/>
  10:        <parameter name="testInfoSaveLocation" value="test-output/" />
  11:        
  12:        <test name="Edit Page Tests" preserve-order="true">
  13:             <parameter name="browser" value="*firefox"/>
  14:             <classes>
  15:                  <class name="com.packageName.BusinessListingPageTests"/>
  16:             </classes>          
  17:             <groups>
  18:                  <run>
  19:                      <include name="single" />
  20:                 </run>
  21:             </groups>        
  22:       </test> 
  23:  </suite>

 

The key to successfully running tests individually lies in lines 17 - 21.  By using groups, you can have your XML test suite run only those tests that you want to run.

The next step requires a few edits to your test classes themselves.  I'm using JAVA in these examples, but I'm sure that the principle relates to other languages as well.

For EVERYTHING you wish to have run along with your tests ( perhaps you have some database setup you want to do) , you must tell the Eclipse/TestNG unholy alliance that you want it to run.  This is simply accomplished by using TestNG annotations, as follows...

 

   1:  @BeforeClass( groups = {"single"} )
   2:  @Parameters({"browser", "seleniumGridIp", "seleniumGridPort", "testServer" })
   3:  public void setUp( String browser, String seleniumGridIp,
   4:       int seleniumGridPort, String testServer) throws Exception {
   5:   
   6:       Selenium sel = new DefaultSelenium( seleniumGridIp, seleniumGridPort,                                                                                                browser,     testServer);
   7:          
   8:       sel.start();
   9:       sel.open(testServer + LoginPage.PAGE_NAME);
  10:       sel.waitForPageToLoad("10000");
  11:  }
  12:   
  13:  @Test( dataProvider = "userSetup", groups = {"single"})
  14:  public void testChangeHoursOfOperation( String userName, String password,String businessId){
  15:       User user = new User();
  16:       user.userName = userName;
  17:       user.password = password;
  18:   
  19:       LoginPage login = new LoginPage(sel);
  20:       login.LISTING_ID = businessId;
  21:       login.setBrowserToStartPage();
  22:       login.loginUserName(user);
  23:   
  24:       assertTrue(amIOnTheStartPage());
  25:  }
  26:   
  27:  @AfterClass(groups = {"single"})
  28:  public void tearDown() throws Exception {
  29:       sel.stop();
  30:  }

 

That's it.  When you run the XML, now your single test will run all by it's lonesome.  When you don't want to run that single test anymore, simply remove the group from the @BeforeClass annotation.  It is very important, though, that you remember to include the group in the annotations for the setUp() and tearDown() methods, or they won't be run.  Its kinda hard to run a Selenium test if the IDE doesn't know where to find the Selenium Server.

 

I hope this helps someone.  If you have any questions, or feedback, please feel free to drop me an email and I'll be happy to clarify any point.

 

If you have the luxury of using an object oriented programming language for testing your web application, there are a few small principles that you might want to keep in mind when coding your tests.

  1. Don’t test a “Page.” Keep your classes and objects as small as possible.
    Do you allow someone to search for things on your website?
      Then have a class/object that thoroughly tests your search.
    Do you have a coupon that shows up  based on the geo-location of a user’s IP address?  Write a class for that.
    Once you have your classes written for each the parts of a page you want to test, create a test file that instantiates those objects and tests them in the integrated format of the webpage.
  2. Have your test do as little work as possible.
  3. Keep the massive work in small functions that are publicly available for the object you are testing.

Do your work in a public method/function:

   1:      public boolean isPartnerLogoPresent() {
   2:          TestTools.debug(DEBUGLEVEL, "isPartnerLogoPresent()");
   3:          if (sel.isElementPresent(partnerLogoId)) {
   4:              TestTools.debug(DEBUGLEVEL, "\tFound the partner logo\n");
   5:              return true;
   6:          } else {
   7:              TestTools.debug(DEBUGLEVEL, "\tCould NOT find the partner logo\n");
   8:              return false;
   9:          }
  10:      }

Have your test call that function:

   1:      @Test
   2:      private void testPartnerLogoPresent() {
   3:          // verify that the Partner Logo is available
   4:          assertTrue(isPartnerLogoPresent());
   5:      }

 

On the surface, this might look as if you are doing a lot of extra typing and extra work, but if you have this partner logo show up on more than one page, all you have to do to verify it there is call this function.

 

“No Failures” does not mean that everything succeeded. 

 

 

 

The Tao of Calvin