Author Archives: g33klady

I have seen the future…

I get involved in a lot of things around technology, especially with kids in Detroit. I love being able to help these kids not only see a future in technology for themselves, but to help them get there.
I became the Vice Chair of the Information Technology Pathway Advisory Board for Detroit Central High School in December of last year. In that role, I’m helping students at Central indirectly – mostly via finding learning opportunities, funding, and advising on curriculum.
A project the sophomores had from March centered around Autonomous and Electric Vehicles, and pulled in curriculum from Computer Programming, Chemistry, Geometry, Art, and Government. The students, in teams of 4, had a few tasks to complete, with the best team taking home some sweet prizes.

  • Computer Programming – Students will assemble, program, and market an Autonomous Vehicle using Lego MindStorm.
  • Chemistry – Students will investigate the pros and cons, efficiencies and inefficiencies, of using battery powered vehicles by assembling battery powered motors.
  • Geometry and Art – Students will design and build a to scale city for test driving their autonomous vehicles.
  • Government – form arguments for/against mock proposals supporting Autonomous and Electric Vehicles

The students had field trips to the M-City autonomous testing location in Ann Arbor and  the GM Battery Lab, and had industry experts join them in the classroom for Q&A.

All of this work culminated in a symposium, held last week. Students presented their work science-fair style, and all of the city blocks they built were placed in the center of the room where the cars were test-driven. Visitors were to go around to each team’s table, hear their arguments and observe their autonomous cars, and vote on who had the best car company, the best designed city block, the most persuasive presentation, and the best overall presentation.

I can’t tell you how impressive this was. These students are pretty amazing! They built the cars, did some programming on the fly, created brands for their cars, stood professionally at their tables and argued their cases. The big winners each got to take home a laptop!

I love working with this school, and feeling like I’m helping to make a difference for them. These students can see, from this symposium, that the community cares about their success, and wants the best for them. I can’t wait to see what we plan for next year!

This slideshow requires JavaScript.

In this video, the students were testing out their vehicles before it was “official” – obviously some reprogramming needed to happen for some! We’ve all been there, though! I reassured some students that I know exactly what it’s like when your code works one minute then it doesn’t as soon as someone else looks over your shoulder ūüėČ

Advertisements

KalamazooX 2018 Recap

Sigh…

KalamazooX is over. Most likely won’t be another one. Not sure what will be able to help me like it has now, but we’ll see.

It’s not just a conference, it’s all of the people that I get to see. Sure I see them individually or in sub-groups other times of the year, but seeing everyone together also makes this special. Seeing my IT family all together, once a year. I hope we find other opportunities to all get together.

Below is the link to the Storify of my live tweeting of KalamzooX 2018. It was remarkable in that at one point, my Twitter account got locked out and I had to prove I wasn’t a robot. I blame Leon Gersing and his insane quotability ūüėČ

Here’s the link: https://storify.com/g33klady/kalamazoox-2018-recap

Kalamazoo X – the last of its kind & an offer

The last Kalamazoo X conference in Kalamazoo is taking place on April 21st of this year. I’m sad to see it go, but excited to see what it evolves into.

I started attending Kalamazoo X in 2012, and I’ve attended every year since. It is a life-changing conference in so many ways!

I’ve written a blurb in the past (here:¬†BestConferenceEver = KalamazooX) to get people to check it out. I live-tweet and then compile every one of them I’ve attended since 2015 (KalamazooX 2015 recap,¬†Kalamazoo X 2016 Recap, and¬†Kalamazoo X 2017 Recap) if you want to get a feel for what it’s like.

I decided that even though I feel like it’s a super cheap conference (only $75 at top price!), some people may still not be able to make it work. I’ve been there, when $75 meant way more than a day of sitting at a conference.

So I want to make an offer to the community – if you want to attend Kalamazoo X this year but can’t for financial reasons, I will buy you a ticket. I’m able to cover 2 people.

But I encourage anyone out there that has gained understanding of the world and themselves, like I have, from this conference, to do the same.

So, let me know if I can help you. Email me – g33klady at gmail dot com – and I’ll hook you up. I believe in this conference that much. And I want as many people to benefit from it as possible!

A Lesson From My Testing Journey

On February 20th, I shared my career journey for the first time to a large audience. I gave a Ministry of Testing Masterclass called “Not All Who Wander Are Lost: A Career Experience Report” (a recording is available for Pro Dojo members here:¬†https://dojo.ministryoftesting.com/dojo/lessons/not-all-who-wander-are-lost-a-career-experience-report-with-hilary-weaver-robb).

I’ve had kind of a wonky career path, and have at times felt some shame for “going backward” from a test lead to “just” an engineer. Now, though, I feel pretty good about my journey – I wouldn’t be who I am today, or where I am, if not for those experiences.

One lesson that I touched on, but I’d like to reiterate here, is to be honest with yourself about what you want to do.

I’ve had testers come to me and ask what their career path should look like, or what they should be aiming for. “What should my end goal be?”

Your career goal is for YOU to decide! Don’t let others make your life plans for you!

For sure, ask for advice about others experience. You don’t have to be a manager. You don’t have to be an architect. You DO have to be happy and fulfilled and grow and learn and get value and give value in your role. I can’t tell you what that looks like for you. Hell, I don’t know what it looks like for me! I’m taking my career a day at a time!

It’s great to have goals, but please, keep your goals flexible! If you realize on the way to becoming a manager that you really want to stay hands on, do that! It’s not the time to stick to your guns like “well, I wrote this down, I have to do it”. Your career should make you happy!

Every day, your experiences change you. You are a different person today than you were when you started your career.

Be honest with yourself about what you want from your career. You might wander a bit, but you won’t be lost as long as your true goal is happiness.

 

Codemash 2018 Recap

It’s taken far too long to put this together! Here are my Storify posts of my live-tweeting the sessions from Codemash January 9-12 2018!

Precompilers (Day 1 and 2):
https://storify.com/g33klady/codemash-2018-precompilers-day-1-2

  • Build a Natural Language Slack Bot for your Dev Team with Michael Perry
  • 3D Printing Lab
  • The Hidden Requirements: Exploring Emotions with Placebos with Damian Synadinos
  • 3D Modeling For Makers and Game Developers with Robert Palmer

Day 3:
https://storify.com/g33klady/codemash-2018-day-3

Day 4:
https://storify.com/g33klady/codemash-2018-day-4

  • I have people skills! The Importance of Emotional Intelligence and Your Career! with Michael Eaton
  • Sondheim, Seurat and Software: finding art in code with Jon Skeet
  • Advanced Patterns for Automated UI Testing with Seth Petry-Johnson
  • Leadership Lessons from World of Warcraft with Ish Amin

We left early as a stupid snow storm was coming in and we needed to get back home.
Another great CodeMash, lots of new stuff for me this year. Looking forward to next year!

24 Hour Hackathons… with dinosaurs!

I recently participated in my company’s 24 hour hackathon. I pulled together my tweets on Storify here:¬†https://storify.com/g33klady/jurassic-hack-ql-technology-24-hour-hackathon-of-2

It was a super cool experience, and I’m looking forward to learning more ūüėÄ

2017 Recap & Looking Forward to 2018

2017 was eventful, to say the least.

I submitted 8 talks to 6 conferences. I was accepted to 5 of those conferences, gave an extra talk at one of them I wasn’t planning on, and was invited to speak at another with a brand new talk. I spoke on life lessons at KalamazooX, making your QA your BFF at CodeStock and Desert Code Camp, and testing RESTful Web Services at CodeStock, Targeting Quality, StarWest, Desert Code Camp, and StarCanada. All of my talks can be found on my Talks page, by the way. I’m open to doing most of them, just ping me ūüėÄ

It was a very busy year for speaking, and I haven’t submitted talks to any conferences yet for 2018. I have some goals around talks for this year, including creating a workshop on REST testing and creating a talk worthy of a TestBash.

Late in the year, I changed teams – I went from being a QA Architect across 5 teams, to working directly with a single team as a sort of Software Engineer in Test. Going from architect to hands on is an interesting transition. Putting all of that theory into practice, and taking your own advice – this is another talk I’m thinking of giving soon. Lots of lessons learned, there.

I want to revamp this site, and blog more. I have a goal of blogging at least once per month. May not seem like much, but it’s more than I’m doing now! I mean, I did the HTTP Status Coop series but that wasn’t much blogging as much as creating images lol

I also took kind of a risk late last year when I contributed to the C# Advent Calendar. I had a lot of impostor syndrome about it – being QA and all. But I did it, and feel pretty ok about it! I got zero direct feedback, though lol lots of traffic to the post and the rest of my site, but no comments. I guess that’s better than negative comments!

I got involved in the community more, as well. I was nominated to Co-Chair of the¬†Computer Programming Pathway Advisory Board of Detroit Central High School. In this position I’m working with the teachers in the school, helping them to build a curriculum that will get these students jobs out of high school, or ready for college.

I’m also trying to do more non-work stuff. Enjoying video games again (can’t get enough Goat Simulator and Minecraft right now!), having screen-free time, tinkering with some things. I’m actually participating in my company’s 24-hour hackathon this year, and I’m super excited to build something new and cool with 3D printed components and IoT!

So my goals for 2018:

  • Create & submit a REST testing workshop to conferences
  • Submit a talk to TestBash
  • Do a talk on going from engineer -> architect -> engineer
  • Make this site look less shitty
  • Blog once a month at minimum
  • Take more risks!
  • Make a difference in the community
  • Take time to recharge (on- and off-line)
  • Build something fun

C# Advent Calendar – Combining Integration and UI Automation in C#

I signed up for the C# Advent Calendar with this post – be sure to check out the rest of the blog posts in the calendar! This post assumes you’ve got some experience with C# and Visual Studio, so I won’t be over-explaining some things. Comment if you get stuck or have questions!

If you’re here for the first time, welcome! I’m a “career QA”, been in the QA/testing field for just over 10 years now. I’ve been doing test automation with C# for several years, including CodedUI, Selenium, and integration tests (using NUnit or MSTest) for REST services, as well as unit testing. So I’m kicking off the C# Advent Calendar with a testing topic. Hope you enjoy!


My talk on Testing RESTful Web Services is all about evangelizing integration testing. Integration tests are sometimes missed between unit tests and GUI tests – developers may think it’s the QA’s job, and QA may think it’s the developer’s job, so they can fall through the cracks.

no_integration_test.gif

So why combine integration and UI tests? These are useful to see if the API and the UI are speaking the same language. They are often developed at the same time by different people, so it’s nice to have a safety net of tests that can be run whenever to verify things are still working properly.

I wrote a very simple web API for funsies (using this tutorial) and because it has an API and a web UI, it seemed like a great subject for this mixed tests treatment! My code can be found at my github, here: https://github.com/g33klady/MontyPythonApi.

Our test will:

  • do a GET via the API for an item
  • launch the UI and search for the same item
  • compare the responses

Creating The Class Library For The Tests

Because this is pretty small, I’m just going to use a single project for my tests. In a larger application I might split them out. I’ll create a Class Library for all of my testing stuff. The first thing I do in general is add all of the NuGet Packages I need.

NuGetPackages

I then set up my structure.

For the UI tests, I know I’ll be using the Page Object Model¬†so I create a folder for those, and add my HomePage class. I also know I’ll need some utility methods, so I add a Utilities class. I’ll wait to add the test classes until I’m ready for them.

ProjectStructure1

Setting Up The Page Objects

In essence the Page Object Model is decoupling the definitions of the elements on a page from the tests that use/manipulate them. This keeps the tests maintainable and not as brittle.

Our page is pretty simple. I’ve pointed out the elements we’ll want to put into the class. We’ll just be typing a number into the text field, clicking Search, and reading the response in the div below that.

webpage_objectsIndicated

Each of my elements has an ID – easily identifiable elements helps us QA folks use the elements in automation. If I have to use Xpath, for example, the tests can be more brittle than if I tell the automation “find this thing with this unique identifier”.

This is what my class looks like with the text field identified:

using OpenQA.Selenium;
using OpenQA.Selenium.Support.PageObjects;
 
namespace MontyPythonApi.Tests.PageObjects
{
	public class HomePage
	{
		[FindsBy(How = How.Id, Using = "prodId")]
		public IWebElement ProductIdInput { get; private set; }
	}
}

The FindsBy is how Selenium will be finding the element, and then the property is of type IWebElement (so Selenium can find it) and I can call it whatever I want. I like to use the type of element it is in the name to make it more clear, especially when there’s tons of elements in there.

I’ll add the rest of the page elements, and then initializing the elements via the PageFactory (part of Selenium.Support.PageObjects):

using OpenQA.Selenium;
using OpenQA.Selenium.Support.PageObjects;
 
namespace MontyPythonApi.Tests.PageObjects
{
	public class HomePage
	{
		[FindsBy(How = How.Id, Using = "prodId")]
		public IWebElement ProductIdInput { get; private set; }
 
		[FindsBy(How = How.Id, Using = "searchButton")]
		public IWebElement SearchButton { get; private set; }
 
		[FindsBy(How = How.Id, Using = "product")]
		public IWebElement ProductDisplayOutput { get; private set; }
 
		public HomePage(IWebDriver browser)
		{
			PageFactory.InitElements(browser, this);
		}
	}
}

Any methods specific to this page will also go here. We can add them as we need them.

Setting Up The Utility Methods

For our integration tests, we’ll need to make HTTP Web Requests, and then get the response back and deserialize it. I prefer to deserialize it in the test itself, but if you want to do it in the utilities be my guest ūüėÄ

Our utility class looks like this (the formatting sucks – check out the code instead here):

using System;
using System.Net.Http;
using System.Text;
 
namespace MontyPythonApi.Tests
{
	public class Utilities
	{
		public static HttpResponseMessage SendHttpWebRequest(string url, string method, string content = null)
		{
			using (var httpClient = new HttpClient())
			{
				var httpMethod = new HttpMethod(method);
 
				using (var httpRequestMessage = new HttpRequestMessage { RequestUri = new Uri(url), Method = httpMethod })
				{
					if (httpMethod != HttpMethod.Get && content != null)
					{
						httpRequestMessage.Content = new StringContent(content, Encoding.UTF8, "application/json");
					}
					return httpClient.SendAsync(httpRequestMessage).Result;
				}
			}
		}
 
		public static string ReadWebResponse(HttpResponseMessage httpResponseMessage)
		{
			using (httpResponseMessage)
			{
				return httpResponseMessage.Content.ReadAsStringAsync().Result;
			}
		}
	}
}

Now We Can Write Our Test!

Now to the good stuff.

I start with the SetUp method, which runs prior to every test. This is where I set the browser driver up – what Selenium uses to make the browser bend to its will.

using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
 
namespace MontyPythonApi.Tests
{
	[TestFixture]
	public class IntegrationAndUiTests
	{
                private IWebDriver browser;
		private static string webUrl;
		private static string apiUrl;
		private static string baseUrl;
 
		[SetUp]
		public void Setup()
		{
			browser = new ChromeDriver();
			baseUrl = "http://localhost:20461";
			webUrl = baseUrl + "/index.html";
			apiUrl = baseUrl + "/api/products";
		}
        } 
}

I instantiate the browser driver (using IWebDriver from Selenium) in the SetUp method because each test will need a new instance of it. Like all good tests, these need to be atomic.

We need a TearDown method as well, to clean up after ourselves.

[TearDown]
public void TearDown()
{		
	browser.Quit();
}

I’m going to set up my test to first make the call to the API, then use an Assert to verify that I got a 200 OK response back. This isn’t necessary but I find it useful – my tests fail here rather then trying to deserialize later on, so I know where things went wrong more quickly.

So we know our test is going to make a call to the API about a product, then verify the data in the web UI. We have a requirement that if a product has a discount price, it’s the only price that will display in the web UI. We set up our test data so that the product with ID = 1 has a discount price, so that will be the subject of our test.

[Test]
public void ProductsDiscountPriceDisplaysOnWebPage()
{
	//API call
	var uri = apiUrl + "/1"; //get the product with ID = 1
	var apiResponse = Utilities.SendHttpWebRequest(uri, "GET");
	Assert.That(apiResponse.IsSuccessStatusCode, 
		"Did not get success status code; got " + 
                apiResponse.StatusCode.ToString());
}

Our test has started to take shape. We are making our call, and getting the response back. We’re verifying¬† it got a 200 OK back but nothing else with it yet.

Let’s deserialize the response, so we can get the discount price value. To do that, I need to add the reference to the API project first, so I can use the model.

Here’s my code now, after having deserialized the response, using the utility method to read the response content into a string:

[Test]
public void ProductsDiscountPriceDisplaysOnWebPage()
{
        //API call
	var uri = apiUrl + "/1"; //get the product with ID = 1
	var apiResponse = Utilities.SendHttpWebRequest(uri, "GET");
	Assert.That(apiResponse.IsSuccessStatusCode, 
		"Did not get success status code; got " + 
		apiResponse.StatusCode.ToString());
	Models.Product product = JsonConvert.DeserializeObject(Utilities.ReadWebResponse(apiResponse));
}

Now we have the data that is returned for the product. We can now launch the web browser with Selenium and get the data returned in the web UI.

I need to have the browser go to the url, and then instantiate my page object:

//WebUI
browser.Navigate().GoToUrl(webUrl);
PageObjects.HomePage page = new PageObjects.HomePage(browser);

Now I can use the properties of page to interact with the elements on the page.

//WebUI
browser.Navigate().GoToUrl(webUrl);
PageObjects.HomePage page = new PageObjects.HomePage(browser);
page.ProductIdInput.SendKeys("1");
page.SearchButton.Click();

I’m essentially typing 1 into the search field, and clicking the search button.

Next I need to read the display of the data as it came back for that product. It comes back in a string with the format <Name> : $<Price> so I’ll need to parse it. Because this is something I’ll be doing on this page for more tests, I’ll add this utility method to the HomePage class.

public string GetPriceFromDisplayText(string displayText)
{
        decimal result;
	Regex r = new Regex("\\$(.*)");
	Match m = r.Match(displayText);
        decimal.TryParse(m.Groups[1].Value, out result);
	return result;
}

Definitely could hit some exceptions along the way, but for now we’ll leave it as-is.

Now our Web call looks like this:

//WebUI
browser.Navigate().GoToUrl(webUrl);
PageObjects.HomePage page = new PageObjects.HomePage(browser);
page.ProductIdInput.SendKeys("1");
page.SearchButton.Click();
var displayedPrice = page.GetPriceFromDisplayText(page.ProductDisplayOutput.Text);

And we can finally add that assert statement to check our values! Here’s our full test:

[Test]
public void ProductsDiscountPriceDisplaysOnWebPage()
{
	//API call
	var uri = apiUrl + "/1"; //get the product with ID = 1
	var apiResponse = Utilities.SendHttpWebRequest(uri, "GET");
	Assert.That(apiResponse.IsSuccessStatusCode, 
		"Did not get success status code; got " + 
		apiResponse.StatusCode.ToString());
	Models.Product product = JsonConvert.DeserializeObject(Utilities.ReadWebResponse(apiResponse));
 
	//WebUI
	browser.Navigate().GoToUrl(webUrl);
	PageObjects.HomePage page = new PageObjects.HomePage(browser);
	page.ProductIdInput.SendKeys("1");
	page.SearchButton.Click();
	var displayedPrice = page.GetPriceFromDisplayText(page.ProductDisplayOutput.Text);
 
	Assert.AreEqual(product.DiscountPrice, displayedPrice, "The prices don't match!");
			
}

Let’s run it and see what we get! Because the API and the tests live in the same solution, we’ll need to open a new instance of Visual Studio to run the tests locally.

Time For Some Results

And… our test fails!

TestResult

There’s a bug in the UI code that should display the discount code. Would we have found this otherwise? Probably with a good unit test, but this is a nice way to combine our tests and see how the application really behaves.

I’m leaving the bug there in the repo, so you can follow along. All of the code demonstrated above is there.

Let me know what you think – is this something you could use? Is this too much overhead for your project? Is this useful?

Using Fiddler AutoResponder for quick service or response mocking

In my Testing¬† RESTful Web Services talk, I touch on service virtualization briefly, and I include a short demo of using Fiddler‘s AutoResponder. I’ve been meaning to look into other (free) tools but haven’t had the chance.

After a question on the Testers Slack, I realized I could do a short blog post on how I demo’d AutoResponder in my talk. It gives a quick idea of the tool and one way you could use it. I love Fiddler*, and there’s so much more you can do than what I’ve been able to use. Please don’t take this post as a “this is the only way you can do things” – I’ll be the first to admit that even though I’ve used Fiddler for years, I feel like there’s so much more to know about it!

*Note: I am not paid by Telerik/Progress for my endorsement; I just love the tool ūüėÄ

Read the rest of this entry

HTTP Status Coop – 503 Service Unavailable

Fourteenth in the HTTP Status Coop series is 503 Service Unavailable!

503ServiceUnavailable_img.jpg

The server is currently unavailable (because it is overloaded or down for maintenance). Generally, this is a temporary state.

via Wikipedia

Cooper says “no way!” ūüėÄ


For the entire HTTP Status Coop series that’s been released so far, head over to the HTTP Status Coop page on my blog!