Skip to content
  • Blog
  • Events
  • Help
  • Careers
  • Contact
New Signature
  • About
      • Company

        New Signature has built a record of leadership by delivering exceptional technology and web solutions.

        View Company

      • Awards

        As a company, we are regularly recognized within the IT industry as well as the communities we serve.

        View All Awards
      • News

        Learn about the newest company announcements, technologies, and products at New Signature.

        View News

      • Partners

        New Signature works with a number of outstanding technology companies to deliver the best experiences to our customers.

        View Partners
      • Leadership

        New Signature's executive team includes proven leaders from the most innovative and fast-growing technology fields.

        View Leadership

      • Industries

        Our solutions are tailored to empower organizations across a wide range
        of industries.

        View Industry Experience
    Close
  • Solutions
      • Intelligent Enterprise
        Solutions

        Going Digital
        Unleash cloud capability, deliver change and compete at speed with a Microsoft digital operating model, enabling you to work more efficiently as you transform your IT environment. Learn More

      • Featured Solution

        Secure Cloud
        In a world of constant threat, ensuring that your underlying cloud platform is protected is the first step on your organization’s journey towards a secure, compliant operating environment. Learn More
      • Intelligent Workplace
        Solutions

      • Secure Workplace

        Work Anywhere

        Endpoint Health

        Identity Health

        Teamwork Support



        VIEW WORKPLACE SOLUTIONS
      • Intelligent Cloud
        Solutions

      • App Factory

        Azure Accelerator

        Azure Launchpad

        Azure Launchpad for DevOps

        Application Health

        Platform Health

        VIEW ClOUD SOLUTIONS
    Close
  • Services
      • Begin your journey towards becoming a digital business with NS:GO, our unique end-to-end framework based on the Microsoft Cloud Adoption Framework.

        NS:GO DIGITAL OPERATING MODEL
      • Intelligent Enterprise

      • Consulting

        We go beyond just technology to help your organization understand how digital can help you uniquely differentiate and better serve your employees and customers.

        VIEW ENTERPRISE SERVICES
      • Intelligent Workplace

        • Identity

          Identity is your new first-line-of-defense. It’s vital to your users and clients that your identity platform is properly configured and secured.

          Endpoint

          Whether your devices are on-premises or remote, personal or business-owned, we can ensure they are properly managed and protected.

          Teamwork

          Today’s workforce is collaborating than ever before.  We can empower your current teams with tomorrow’s progressive technologies.

          VIEW WORKPLACE SERVICES
        • Intelligent Cloud

          • Platform

            The cloud is no longer some future-state. It’s the here and now. Adopting a cloud-first platform is one of the best ways to maintain a future-proofed competitive advantage.

            Applications

            We build cloud-native apps and modernize legacy systems with the power of Azure to give your organization a competitive edge.

            Data

            We can help your organization create secure, scalable data platforms to deliver simpler and more sophisticated insights to your business.

            VIEW CLOUD SERVICES
        Close
      • Client Stories
          • Case Studies

            Browse a comprehensive list of companies who have created successful partnerships and experienced transformative solutions with New Signature.

            View All Case Studies

          • Featured Case Study TalkTalk Modern Workplace

            New Signature worked with TalkTalk to define a new Modern Workplace solution based on Microsoft 365, which kept the user firmly at the center of the transformation.
            View Case Study

          • Testimonials

            We love transforming our customers businesses, take a look at what they have to say about New Signature.

            View Testimonials

          • Featured Testimonial Davis Construction

            With New Signature’s help, Davis was able to take a progressive step forward by migrating their private branch exchange (PBX) phone system to a Voice of Internet Protocol (VoIP) system.
            View Testimonial

        Close
      • Explore
          • Guides & Ebooks

            Dive deeper into education with your team by leveraging our expert-developed guides and eBooks.

            View All Guides & Ebooks

          • Infographics

            Rich with statistics and information, our infographics are great tools for quick but insightful learning.

            View All Infographics
          • Podcast: Office Explorers

            Join Kat and Rob monthly as they chat with New Signature experts and explore the world of O365.

            Listen to Podcasts

          • Videos

            Visit our videos stream to access recorded webinars, service information and to learn more about us.

            WATCH ALL VIDEOS
          • Flyers

            Searching for information about our services? Our flyers are a great takeaway for all those details.

            VIEW ALL FLYERS

          • Featured Stream

            Learn more about the tooling and expertise required to unlock productivity and mobilize your teams.

            MODERN WORKPLACE
        Close
        Close
      Blog

      Build a More Fluent API With Generic Extension Methods

      New Signature / Blog / Build a More Fluent API With Generic Extension Methods
      December 2, 2016December 2, 2016| Jamie Fraser
      • Facebook
      • Twitter
      • LinkedIn
      • Print

      This is the second in a bunch of posts I have in my head around UI automation testing.  Go back and read the first for some more background on why I like this topic.  I promise this one is a quicker read.

      Fluent Interfaces are what all the cool kids are doing these days.  If you’re not up to speed, here’s a link to get you started.  Go ahead and read it – it’s an easy read, and I’ve got all the time in the world.

      Welcome back.  To review, a fluent interface aims to make code more readable with method chaining being a big part of how it accomplishes this.  Fluent interfaces are self-referential and usually terminate with a void return.

      In C#, fluent interfaces are enabled using extension methods.  Extension methods are ways to “bolt” functionality onto a class without having to inherit from it.  That’s nifty in other scenarios as well – if you want to extend a sealed class for instance.  In the case of a fluent interface, the idea is to always return the type you’re extending in your extension methods until you get to a completion.  Completions return void, or if you’re not feeling pure they could simply return a different type with the result you’re looking for. You can also switch types as you move through a process, making this approach a great way to implement a workflow.

      Right now, I’m super-interested in UI automation for testing.  Actually, I’m kind of obsessed.  UI automation just feels like magic to me – work out your test case steps once, sprinkle a little code around and voila!  You don’t have to click those buttons again – a computer will do the work for you.  I’m sure a beachside life filled with Mai Tais and riches will follow.  I love the idea of a fluent interface for writing test cases because the flow of the case is much more readable.  That helps us reason about what a test is doing.  Here’s an example:

      
      [TestCase("redacted", "redacted", ExpectedResult = 4)]
              public int TestSecurityTrimmedActionButtons(string UserName, string Password)
              {
                  int count;
                  browser.LoginDriver()
                          .Login(UserName, Password)
                          .ActionsDriver()
                          .ViewSubmission()
                          .GetCountOfActionButtons(out count)
                          .Logout();
                  return count;
              }
      

      I think that’s pretty clear – login, view an item, figure out how many “action buttons” there are, and get out of Dodge. There’s a bit of code in behind each of those methods, but there’s pretty good separation of concerns and it’s pretty DRY. Not a terrible piece of work.

      The API I’m building is designed around the concept of screen drivers – there’s a separate driver for every screen in the application being built, and I build extension methods for those drivers’ types. Note that the concept of a “screen” is a bit loose – sometimes I’m implementing drivers for controls or frames that appear on different screens – that’s all in the name of writing less code, so I don’t mind that my metaphor doesn’t completely stand up to scrutiny. The goal is more mai tais and riches, not more toiling over a hot keyboard. The drivers themselves are just shims that provide the scaffolding for the extension methods, but they could definitely do more if needed. All drivers inherit from ScreenDriverBase, shown here.

      
      public class ScreenDriverBase : IScreenshot
          {
              public void Logout()
              {
                  var browser = Mvx.Resolve();
                  var logoutButton = browser.FindElement(By.ClassName("login-logout"));
                  Actions actions = new Actions(browser);
                  actions.MoveToElement(logoutButton);
                  actions.Perform();
                  logoutButton.Click();
                  WebDriverWait wait = new WebDriverWait(browser, new TimeSpan(0, 0, 30));
                  wait.Until((b) =>
                  {
                      return b.FindElement(By.Id("sfLoginWidgetWrp")) != null;
                  });
              }
          }
      
      

      You can’t help but notice that ScreenDriverBase implements the Logout() method. That’s probably a bit dirty, but to me it seemed like the logical place to put this code – you want to be able to logout at the end of any process, and each process is driven by a different screen or screens. I could have implemented this as an extension of ScreenDriverBase but this actually feels more natural to me for this particular case. Sound off in the comments if you think this is a terrible, awful, rotten thing. I’m all ears.

      So that’s the setup. Here’s the magic.

      I want to be able to take screenshots as I proceed through my test. That’s super-helpful, because even if a test passes the screen could still have some layout issues that my robot helper isn’t going to notice. Screenshots let testers quickly flip through a bunch of pictures looking for anomalies. They’re also helpful when tests fail – the screenshots can show you the state of the screen when things went pear-shaped, which helps developers quickly diagnose what the problem is. I don’t want to implement a screenshot method on every class, and I don’t want to break my fluent interface so I need a way to return to the type of the driver I’m currently working with, preferably from the instance of the type I already have. Finally, since I’m implementing my fluent interface with extension methods, I need to extend all my drivers and manage the return magic in an extension method, and I shouldn’t do that in a surprising way – life for the people after me will be more enjoyable if I put all like things in the same place. While I’m enjoying mai tais on the beach.

      Recall that generic methods are a bit of compiler sugar that let developers write methods with type parameters. The thing I hadn’t really thought about with generics before is that you can not only declare a method like

      
      static void Swap(ref T lhs, ref T rhs)
      
      

      You can also declare a method like

      
      public static T ScreenShot(this ScreenDriverBase driver,string StepName) where T : class
      
      

      Being able to have the return type be generic means that I can now have this extension method that applies to anything that inherits from ScreenDriverBase return whatever the specified type is. The declaration above isn’t ideal yet, because the where T : class means that I can give any reference type as a type parameter. That means I could use, say, object and the compiler would think that was groovy. From a design perspective, that’s not so groovy – I want to keep everybody on this fluent interface rail that I’ve put them on, so a better choice is

      
      public static T ScreenShot(this ScreenDriverBase driver,string StepName) where T : ScreenDriverBase
      
      

      Now I’ve constrained everybody to passing in something that inherits from ScreenDriverBase ensuring that I get at least a ScreenDriverBase back from the screenshot method. To get the actual return I want, all I have to do is

      
                  try
                  {
                      return (T)Convert.ChangeType(driver, typeof(T));
                  }
                  catch (Exception)
                  {
                      return default(T);
                  }
      
      

      In fact, since I’ve already constrained T to be a class, and more specifically some inheritor of ScreenDriverBase, I can just do a safe cast and call it a day:

      
                  return driver as T;
      
      

      Technically that second way is less safe, but I believe I’ve boxed things in enough to be protected – if you’re feeling conservative, the first way is the way for you. Whichever way I go, my developers and testers can party over the returned driver. Testers can now pop screenshots in wherever makes sense for them with very little effort. Hoorah!

      
              [TestCase("submitter1", "submitter1", ExpectedResult =4)]
              [ScreenshotAction]
              public int TestSecurityTrimmedActionButtons(string UserName, string Password)
              {
                  int count;
                  browser.LoginDriver()
                          .Login(UserName, Password)
                          .ActionsDriver()
                          .ScreenShot("Login")
                          .ViewSubmission()
                          .GetCountOfActionButtons(out count)
                          .Logout();
                  return count;
              }
      
      
      Categories
      Tips and Tricks
      Contact New Signature

      Events

      Thu 28

      Power Platform Series: Drive Organizational Productivity with Power Virtual Agents

      January 28 @ 10:00 am - 10:45 am EST
      Feb 16

      Cognizant’s Experience Lab for Continuous Testing with Azure

      February 16 @ 12:00 pm - 2:00 pm EST

      View More

      New Signature
      New Signature HQ
      901 K Street NW, Suite 450
      Washington, DC 20001
      Phone: 202-452-5923
      New Signature Canada HQ
      7th Floor, 5140 Yonge Street
      Toronto, ON M2N 7J8
      Phone: 416-971-4267
      New Signature UK HQ
      57 Bermondsey Street
      London SE1 3XJ
      Phone: +44 (0) 845-402-1752

      About

      • Company
      • Awards
      • News
      • Leadership
      • Partners
      • Industries

      Solutions

      • Intelligent Enterprise Solutions
      • Intelligent Workplace Solutions
      • Intelligent Cloud Solutions

      Services

      • GO
      • Intelligent Enterprise
      • Intelligent Workplace
      • Intelligent Cloud

      Client Stories

      • Client Stories
      • Testimonials

      Explore

      • Guides & Ebooks
      • Podcasts
      • Flyers
      • Infographics
      • Videos
      Copyright © 2021 New Signature
      • Blog
      • Events
      • Careers
      • Help
      • Anti Slavery
      • Privacy Policy
      • Contact
      • About
        • Company
        • Awards
        • News
        • Leadership
        • Partners
        • Industries
      • Services
        • GO
        • Intelligent Enterprise
        • Intelligent Workplace
        • Intelligent Cloud
      • Client Stories
        • Case Studies
        • Testimonials
      • Technologies
      • Explore
        • Guides & Ebooks
        • Infographics
        • Podcast: Office Explorers
        • Videos
        • Flyers
      • Blog
      • Events
      • Careers
      • Contact
      • Search
      Cookie Settings
      New Signature uses "Required Cookies" to run our website, "Functional Cookies" used by third parties to personalise marketing, including social media features.

      Change your preferences by clicking the “Cookie Settings” link at the bottom of every page. Learn more about cookies in our Cookie Policy and our Privacy Policy. By clicking the “Accept Cookies” button below, you consent to our use of cookies.

      Please note that “Required Cookies” will be set regardless of your consent.
      Cookie SettingsAccept Cookies
      Privacy & Cookies Policy
      Performance

      Performance Cookies provide Content Delivery Network assets that deliver faster site content delivery capabilities.

      Required

      These cookies are required mainly in order to deliver Multilanguage site capabilities.

      Functional

      Functional Cookies allow us to provided advanced media capabilities including videos, surveys and other multimedia capabilities.

      Disabling Functional cookies will block the playing of videos and other multimedia site components.

      Targeting

      Targeting Cookies are used to capture user information in order for New Signature to deliver better user experiences.

      Save & Accept