Excel as a Test Management Tool

Because you're going to use it anyway...

Ruby-Selenium Webdriver

In under 10 Minutes

%w or %W? Secrets revealed!

Delimited Input discussed in depth.

Managing Knowledge Transfer Sessions

Read the article, grab the templates

Ask questions

If you don't ask, you won't learn. You won't teach either.

Wednesday, 8 March 2017

100 Day Deep Work - Day 6: Checking Multiple Links using WebDriver



Here we are, Day 6 and pretty much a continuation of yesterday. I suppose I should say refinement or refactoring. Compared to the approach taken in yesterday’s session I scaled this right back to something simpler. Why? Here comes today’s (and yesterday’s) real learning.

I was breaking the golden rule of taking it one step at a time. Instead I was trying to work out what the overall solution looked like then code it up. That was doomed to failure so I went back to baby steps and simplified things.

First off, recall the (cut down) testing problem from yesterday:
You have a website with 2 navigation links. The expectation is more links will be added in the future. The test must check the known set of text links are present and if any new ones have been added.

That’s the first part so let’s work out some code for that.

Here’s the list of expected links:

public enum links
{
    News,
    Sport
}

We need to a) locate the links section and b) count how many links there are on the page:

var locateTheLinkSection = 
Driver.Instance.FindElement(By.XPath("//ul[@class='nav-tabs']"));

var actuaLinkSetCount = locateTheLinkSection.FindElements(By.TagName("a")).Count();

Good, we have a count of what is on the page, but is that what was expected?

var expectedLinkSetCount = links.Count();

Console.WriteLine($"Expected link Set Count is {expectedLinkSetCount}.");
Console.WriteLine($"Actual link count is: {actuaLinkSetCount}");

We could wrap this in an if-else or a try-catch to actually DO something given the outcome, but that’s a way to get our check done.

I’d still like to report what was new, what actual links got found, etc. not just a count - but that’s something to look at later.

Good, onto day 7!



Tuesday, 7 March 2017

100 Day Deep Work - Day 5: Iterating Over Links



Day 5 of the 100 Day Deep Work challenge!

Today’s session was a bit all over the place. I spent most of the time imagining what I think the solution to my current problem could be, than actually solving the problem in code. Such is the way sometimes I guess but I certainly look forward to having mental models of code patterns in my mind to apply more readily.

Here’s the problem:
You have a website with 4 navigation links, 3 are text and 1 is a link under a company logo. The expectation is more links will be added in the future, they might be text or images. The test must check the known set of text links or linked images are present and if any new ones have been added. If new ones have been added, this should simply be reported and the known set tested anyway. The classes/methods for this must be reusable, to cover other sets of links across the website.

To do this I started splitting out the list of known links into a Dictionary

        public static IDictionary<stringstring> knownTextLinkAndURLList
            = new Dictionary<stringstring>
           {
                { "News","http://www.bbc.co.uk/news/" }
                { "Sport","http://www.bbc.co.uk/sport" }
            };


Then I created a method to loop over the links by looking for the link text

       public static void TopNavigationLinksCheck()
        {
            foreach (var navigationLink in knownTextLinkAndURLList.Key)
            {
                if (IsElementPresent(By.LinkText(navigationLink)))
                {
                    Console.WriteLine($"As expected, I saw: '{navigationLink}' link text");
                }
                else
                {
                    Console.WriteLine($"I could NOT locate the link: {navigationLink}");
                    TakeScreenshot.SaveScreenshot();
                    var pageNavigationElementException = $"I expected {navigationLink} but it was not located";
                    throw new Exception(pageNavigationElementException);
                }
            }
        }


Which used a reusable extension in the If statement I copied down from Stack Overflow:

        public static bool IsElementPresent(By by)
        {
            try
            {
                Driver.Instance.FindElement(by);
                return true;
            }
            catch (NoSuchElementException)
            {
                return false;
            }
        }

This seems fine for checking over text links, but we need to do that then check the actual link is correct. This is assuming we're concerned link text may be written incorrectly / against an agree style and that the link applied might vary, say news.bbc instead of bbc.co.uk/news for example.

Two things to investigate further then; 1) How to check both link text and link, 2) How to confirm there are no new links added (we can already check if any are removed or their links changed)

Day 6 here we come!

Mark.

(Be sure to have a look at the book - Deep Work)
-------------------------------------------------------------------------------------------------------------
Day 4: http://cyreath.blogspot.co.uk/2017/03/100-day-deep-work-day-4-configuration.html

Monday, 6 March 2017

100 Day Deep Work - Day 4: Configuration Files for Usernames and Passwords




Day 4 of the 100 Day Deep Work challenge actually happened on Friday, but as I don’t do IT stuff at the weekends here’s the posting today!

One thing I’ve been doing for simplicity sake is putting the various usernames and passwords used in tests into its own Class file. As I’m always working on test systems it didn’t seem to be an issue. However, the general convention is that these Usernames and Passwords should be protected to align with the security policy of the company you’re testing for.

That makes sense, after all you might have an Admin user who’s details make it into a live deployment. With tester tests integrated into the same place as unit tests and code, the risk is there. 

So, how to move those details out of the Class file and include them in the Configuration file?

Configuration Settings
In Visual Studio’s ‘Solution Explorer’ you’ll see your project has an app.config file, double click and open it. Inside the configuration elements we can add appSettings and include details of our username and password as a key/value pair.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="AdminUsername" value="testuser" />
    <add key="AdminPassword" value="Password1"/>
  </appSettings>
</configuration>

Naturally a lot more can be added here, such as system configuration details, but for now let’s stick with these two items.

Calling the appSettings items
To call the items from the app.Config file we need to add a call to our test like this:
        LoginCommand
            .LoginAs(ConfigurationManager.AppSettings["AdminUsername"])
            .WithPassword(ConfigurationManager.AppSettings["AdminPassword"]);

In practice however, I’m seeing the norm appears to be to call the AppSettings items via a separate file. I’m not 100% sure why at this point, but I’m assuming this is further abstraction. Moving anything that might change even further up to the page object level and out of the test. For example we might create a separate class to hold the user list for this test

    public class UserList
    {
        public const string TheUsername = "AdminUsername";
        public const string ThePassword = "AdminPassword";

    }

In which case we’d change our test to a more generic:

        LoginCommand
            .LoginAs(ConfigurationManager.AppSettings[UserList.TheUsername])
            .WithPassword(ConfigurationManager.AppSettings[UserList.ThePassword]);

Not a complete understanding but a good start - more tomorrow

Saturday, 4 March 2017

100 Day Deep Work - Day 3: C# Enumerations, Dictionaries and Looping



100 Day Deep Work challenge, day 3!

This week I was trying to find/learn a way to create pattern of code in some of the automation I’m working with. The pattern would allow the listing out of collections of items, say links or page tabs, then iterate over each one testing they are working as expected.

Page Object / Page Flow
There are some simple ways of doing this, but the challenge was to follow coding standards used in the project. One aspect of which is to follow the Page Object / Page Flow model. Essentially that means having automation tests that are separated from the code that describes the page elements and how we interact with them. So how to create a test that can call page-stuff in a generic way.

Enumeration
Enums in C# allow us to make unordered lists of items (I learned there is an ordered list too), like links or tabs, then use them in other things like Dictionary lists. Where we could then have values (definitions) assigned to the list items. That seemed like a good way to declare an item of interest to check in the test and give it the ID as a string from the HTML on the page.

Here’s what the main pieces of the header section I wanted to find looked like in an enumerated list.

    public enum enumElements
    {
        Logo,
        ApplicationName,
        Welcome,
        OrgSelector
    }

Dictionary
To assign each of these items of interest a string value that matches the ID in the HTML I used a Dictionary list, knowing I could pull out the value element (the string) later for use in the actual test. Here’s how the Dictionary pulled in the item and assigned the value.

public static IDictionary<enumElements, string> ItemName
            = new Dictionary<enumElements, string>
        {
            { enumElements.Logo, "logo" },
            { enumElements.ApplicationName, "application-name" },
            { enumElements.Welcome, "welcome" },
            { enumElements.OrgSelector, "org-selector" }
        };

The Unit Test
The objective here was to see if I could build a Unit Test that did NOT contain the actual values being tested. The idea there of course being that if the page changed, the test would still stand; just the underlying values would need changing. (Idea: can we make the dictionary items more generic?)
Here’s the Test Method from the unit test:

        [TestMethod]
        public void TestMethod1()
        {
            foreach (var item in ItemName.Values)
            {
                Console.WriteLine($"We have: {item}");
            }
        }

The theory here being – if we can do a WriteLine on each item Value, then we could replace Console.Writeline with meaningful Selenium test code. That could be asserting the presence of each item in the page for example or clicking on it. Running the test worked and the output was a list of the string Values.


Phew! That only took 2 days, but now we have a pattern for building a list of pretty much anything and testing them in an iterative fashion. Literally, if we have a set of links, tabs, items in a drop-down; the above will make it easy to test them.

Weekend break then back to it Monday!

Thursday, 2 March 2017

100 Day Deep Work - Day 2: Comparing Expected and Actual Values



Thoughts, discoveries and blockers from Day 2, posted a bit late as I was having some computer issues last night, got to love system updates!

The plan yesterday was to study iterating over multiple elements of a page using Selenium, such as sets of links or dropdown items. It’s one of those problems where I’ve solved it before but I always felt it was in a crude way. However, I got entirely side tracked by the idea of identifying the Div section in which a set of links, for example, might appear instead of the individual links. That feel more like a general UI based test, whereas checking for individual links is more a unit test.

It all depends on the purpose of the test of course, but at the UI level we really should be looking at user journeys and workflow, how the user traverses the site’s functionality to achieve a specific goal. Not so much the assertion of individual elements just for the sake of it, that’s more of a unit level test. I feel that assertions of elements on the page should be limited to ensuring those that are needed for the test are in place. I’ve seen a pattern of testing for first and last items to load on the page or just waiting for a document.Readystate is complete (1, 2).

Turning back to the main thrust of yesterday, here’s example code for a pattern of declaring what we’re looking for then asserting we found it.

        public static void CheckWeHitTheRightPage()
        {            var homepageWelcomeMessage = Driver.Instance.FindElement(By.CssSelector("div.zone.zone-content > h1")).Text;
            var expectedHomePageText = "Welcome to the Website";
             if (homepageWelcomeMessage == expectedHomePageText)
            {                Console.WriteLine("As expected, I saw '" + homepageWelcomeMessage + "' on the home page.");
            }            else            {                Console.WriteLine("I could NOT confirm we're on the Home Page");
                var homePageException = $"I expected ' {expectedHomePageText} ', but I saw ' { homepageWelcomeMessage } '.";
                TakeScreenshot.SaveScreenshot();
                throw new Exception(homePageException);
            }         }

There’s some extra bits in there like capturing a screen shot but you’ll get the idea. I’m was quite happy with the pattern until I tried it to find a Div, as mentioned above. The below code does NOT work in the context I was trying it. When Writeline outputs what was returned for the value of topNavClassName it comes back as OpenQA.Selenium.Firefox.FirefoxWebElement each time. Clearly comparing that with a

        public static void validateTopBarNavigationIsPresent()
        {             var expectedTopNavClassName = "container-fluid";
             // Find the navigation element container to check it loaded            var topNavClassName = Driver.Instance.FindElement(By.ClassName("container-fluid")).ToString();
                 Console.WriteLine($"The variable topNavClassName contains the value: {topNavClassName}");
             // OR perhaps it's better to find it this way?            //IJavaScriptExecutor js = Driver.Instance as IJavaScriptExecutor;            //string topNavClassHTML = (string)js.ExecuteScript("return arguments[0].innerHTML;", expectedTopNavClassName);            //Console.WriteLine($"The variable url contains the value {topNavClassHTML}");             if (topNavClassName == expectedTopNavClassName)
            {                Console.WriteLine($"I found the main navigation Div by its Class Name: {topNavClassName}");
            }            else            {                Console.WriteLine("The main navigation Div was NOT located on the page");
                var topBarNavigationException = $"I expected to find the main navigation Div of 'container-fluid', but instead I got {topNavClassName}";
                TakeScreenshot.SaveScreenshot();
                throw new Exception(topBarNavigationException);
            }        }

I also investigated if pulling the Class from the HTML might be a way forward (see the commented out part of the code) but I hit the same issue. That issue being IWebElement and a String can’t be compared so we have to tack on the ToString() on the end of the line where we find the Class name. That way it’ll be accepted and the solution can be built. But still, it comes back as OpenQA.Selenium.Firefox.FirefoxWebElement each time.

We can change the condition in the If statement from if (topNavClassName == expectedTopNavClassName) to if (topNavClassName != null) and we get a result. The issue is I want to know what topNavClassName actually contains. Or do I? If I change the name of the class is does fail, such as to ClassName("container-fluidsss"). So maybe that’s enough. It would be more reassuring to know what’s in there. Frustrating.

Hmm, well onto day 3!

------------------------------------------------------------------
Day 1: http://cyreath.blogspot.co.uk/2017/02/100-day-deep-work-day-1-c-namespaces.html
Day 0: http://cyreath.blogspot.co.uk/2017/02/100-day-deep-work-day-0-learning-plan.html
------------------------------------------------------------------

Links and References