<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><title type="html">wltester</title><subtitle type="html" /><id>http://blogs.msdn.com/b/wltester/atom.aspx</id><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/wltester/" /><link rel="self" type="application/atom+xml" href="http://blogs.msdn.com/b/wltester/atom.aspx" /><generator uri="http://telligent.com" version="5.6.50428.7875">Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><updated>2011-09-13T11:39:00Z</updated><entry><title>Overcoming UI Automation Challenges</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/wltester/archive/2012/03/05/overcoming-ui-automation-challenges.aspx" /><id>http://blogs.msdn.com/b/wltester/archive/2012/03/05/overcoming-ui-automation-challenges.aspx</id><published>2012-03-06T02:37:52Z</published><updated>2012-03-06T02:37:52Z</updated><content type="html">&lt;p&gt;UI automation isn’t an easy task, as any UI feature test owner who is responsible for automating their areas can tell you. It is quite challenging in terms of getting more test coverage and higher test reliability from automation. Let's discuss these challenges in more detail.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;From the test coverage perspective:&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Each automated test consists of two parts: the code to drive the product and the code to validate the test result. Many product teams have a coverage goal of 70% or higher. Without help from developers' unit tests, it is actually quite difficult to achieve this goal by UI automation tests alone. Here are 3 main reasons: test hooks, result validation, and cost/complexity.&lt;/p&gt;  &lt;p&gt;1) Some UI controls can't be seen (or found) by the UI automation framework being used. This is either due to some technical limitations of the UI automation framework or the accessibility support for the UI controls not implemented properly in the product code. Either way, this often prevents common tests from being automated until the problems are resolved.&lt;/p&gt;  &lt;p&gt;2) Test validation often is not easy, especially for UI tests or UI changes that require manual verification from testers. Many teams are trying to solve this problem by developing tools or using techniques like screenshot comparison, video comparison, etc. But these tools can't replace human testers very well because they usually cause higher rates of false positive or false negative results in automation tests. As a result, many UI tests like these won't be automated.&lt;/p&gt;  &lt;p&gt;3) Complex UI test scenarios have more steps involved, which potentially adds more cost to the automation effort and may introduce more instability to the tests. From an efficiency perspective, sometimes it is much cheaper to run the tests manually rather than spending time automating them, especially when there is a short product cycle. Also, it is difficult to manually trigger most error messages and difficult to automate them. For this reason, we are not able to achieve the test coverage we want from our automated tests.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;From the pass rate (reliability) perspective:&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Ideally, tests fail when the product breaks. But this is not always the case for complex projects. Sometimes no matter how hard they try, test owners still need to spend time fixing their tests as part of their daily routine. This is, of course, a headache that they try to avoid. Unfortunately, there isn't a quick or easy solution to remedy this. Here is why:&lt;/p&gt;  &lt;p&gt;1) Timing issues are one of the most common and annoying problems that we encounter in UI automation. The product code and the test code usually run in different processes, which sometimes results in their getting out of sync. It isn't easy to handle or debug a timing issue. Some testers run into situations where their test continues to fail although it has been fixed over and over again. Every time there is a UI state change in a product, it creates a potential timing issue for UI automation. To handle a timing issue properly in test code, waiters (UI event listeners), ETW events, polling, or even &amp;quot;sleeps&amp;quot; are often used. Since timing issues can be difficult to reproduce, it might take a few tries before the root cause is determined and the proper fix is applied.&lt;/p&gt;  &lt;p&gt;2) Each UI automation test is designed and written based on the expected product behaviors, UI tree structure and control properties. So if a developer changes a product behavior or UI layout, or modifies a control property, that could easily break automated tests. When that happens, testers will need to spend time to debug and fix their test failures. If there is an intermittent issue in the product, debugging the test failure to figure out the root cause is even tougher. In this case, test logs, product logs, screenshots and videos for the failing test state are needed for debugging. Sometimes, additional test logging is required to help debug the problem. In the early product development stage where the product and test automation are not yet stabilized, the test code is always assumed &amp;quot;guilty&amp;quot; by default until proven &amp;quot;innocent&amp;quot; when there is a test failure.&lt;/p&gt;  &lt;p&gt;3) We all know that there is no bug-free software out there. So it shouldn't be a surprise that issues from the operating system, network, backend services, lab settings, external tools, or other layers account for many automation test failures. Since those are external issues, testers have to implement less than ideal workarounds to fix their automation failures, which is very unfortunate. Please keep in mind that workarounds for external issues don't always work well because they often band aid problems only. &lt;/p&gt;  &lt;p&gt;UI automation remains one of the biggest challenges and a significant cost for test teams in product groups in the upcoming years. Below are some proposed ideas on how to mitigate the UI automation challenges discussed above:&lt;/p&gt;  &lt;p&gt;1) Choose a UI automation framework that fits your automation requirements. Four major criteria can be used when testers write prototype tests during the framework evaluation.&lt;/p&gt;  &lt;p&gt;- Performance: how fast your tests can be run&lt;/p&gt;  &lt;p&gt;- API Supports: how easily you can build your own OMs and tests and how many major test scenarios can be automated with the framework&lt;/p&gt;  &lt;p&gt;- Reliability: how stable your tests can be (are your tests flaky because of the framework?)&lt;/p&gt;  &lt;p&gt;- Maintainability: how easily you can update your existing test OMs when there is a UI/behavior change in the product&lt;/p&gt;  &lt;p&gt;2) Work closely with your developers to add testability (such as accessibility supports and automation IDs for UI controls) needed by your automation. Searching for UI controls by their&lt;a href="http://msdn.microsoft.com/en-us/library/aa349646.aspx"&gt; automation IDs&lt;/a&gt; is usually the preferred way because that can reduce some localization support for non-English builds.&lt;/p&gt;  &lt;p&gt;3) Make sure to use a waiter or other waiting logic every time there is a UI state change or a timing delay in the UI after triggered by a test step.&lt;/p&gt;  &lt;p&gt;4) Understand your product behaviors and pay attention to detail. Again, UI automation tests are written based on expected product behaviors. In other words, any unexpected product behavior could potentially break your tests. Your tests will become more reliable if you can properly handle product behaviors in various situations.&lt;/p&gt;  &lt;p&gt;5) The cost for UI automation is actually a long term investment and isn't cheap. So do not try to automate every test. We can't afford to do that anyway since we always have other tasks to do. Before you decide to automate a test, you should ask yourself a couple of questions first: is it worth the effort to automate this test? What is the gain vs. the cost? Basically, almost everything can be automated, the difference being the cost. Here are 3 areas that we can start first: a) BVTs (Build Verification Tests) and performance tests; b) common P1 test cases; c) test cases that provide high coverage with reasonable cost (under 2 days). After that, then we can continue to automate more test cases if time allows.&lt;/p&gt;  &lt;p&gt;6) Find and leverage (maybe develop) more tools to help validate results for UI tests.&lt;/p&gt;  &lt;p&gt;7) Identify the root cause of a test failure and fix it completely in the right place. Do not just band aid the problem. For example, try to remove or not use SLEEPs!&lt;/p&gt;  &lt;p&gt;8) If a test failure is caused by an unexpected product behavior, push the development team to fix the issue. Do not try to work around the issue in test code as that will hide a product bug.&lt;/p&gt;  &lt;p&gt;9) Write less automated tests and focus on achieving a higher test pass rate in the early stages of product development. That will help reduce the cost for test case maintenance. Once the product is stabilized, then write more test automation and focus on the code coverage goal.&lt;/p&gt;  &lt;p&gt;10) Abstract test cases from UI changes to reduce the test maintenance cost. Please see the article on &lt;a href="http://blogs.msdn.com/b/wltester/archive/2011/11/14/object-model-design.aspx"&gt;Object Model Design&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Wei X. Feng, Microsoft&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10278145" width="1" height="1"&gt;</content><author><name>Windows Live Tester</name><uri>http://blogs.msdn.com/wltester_4000_hotmail.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Service Upgrade Testing</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/wltester/archive/2012/01/05/service-upgrade-testing.aspx" /><id>http://blogs.msdn.com/b/wltester/archive/2012/01/05/service-upgrade-testing.aspx</id><published>2012-01-06T01:17:46Z</published><updated>2012-01-06T01:17:46Z</updated><content type="html">&lt;p&gt;To bring the windows live experience to life, we host a variety of interconnected services. These are large scale services which run on thousands of servers, and due to their scale cannot be upgraded atomically. One of the challenges is making sure that when one of these services is upgraded, the rest of the system works properly. Upgrades to the full site require a coordinated test effort that often involves running one service against multiple versions of another.&amp;nbsp; To ensure that upgrades go smoothly, Windows Live has several strategies to make sure that all the versions to which our users will be exposed during a release are covered.&lt;/p&gt;
&lt;p&gt;Keeping the state throughout upgrades&lt;/p&gt;
&lt;p&gt;When testing an upgrade in a stateful system like ours, we need to think about how the new version of the software will interact with preexisting state and data. It is a common mistake to only test a service with data created using the new version, when existing customer data has been around for much longer and has gone through multiple upgrades and migrations. The question is how we replicate this state in our labs, particularly using our automation. Some of our approaches are the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li value="1"&gt;Know your data scenarios: One strategy is having a list of the relevant user data scenarios&amp;nbsp; and having multiple instances of each of them provisioned in our lab. We can then check on the state of the data throughout the upgrade. Without knowing the states that the user can be in, it is hard to make sure that they will be working on the new version.&lt;/li&gt;
&lt;li&gt;Build automation for upgrades: Generally test automation has a setup, execution and verification stage. However, when defining tests for upgrade scenarios, we can think about pre-upgrade setup steps and post-upgrade validation steps. We can then structure tests so that, before the upgrade begins, we run the setup step, and then on each step of the upgrade we run any number of validation actions. Building tests designed for upgrades gives us the ability to automate the process of testing an upgrade.&lt;/li&gt;
&lt;li&gt;Run a practice upgrade: It is always good to have an environment in the labs which has gone through the same upgrade steps as production has, with accounts that have gone through the same migration process.&amp;nbsp; This often lets us detect unexpected issues that we did not catch through our automation.&lt;/li&gt;
&lt;li&gt;Test throughout the full upgrade: Beyond having tests that run after each upgrade step, another strategy is to have tests that are continuously running during the upgrade. These tests start with an existing user state, and execute operations with corresponding verification steps as the upgrade runs through. This lets us find issues that may only happen when the upgrade is actually running.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Another interesting issue that comes when upgrading stateful systems is when old versions of client software cannot support state created with new versions of the service. Testing an upgrade that covers both client and server scenarios requires us to consider the version matrix and test each combination. Often this matrix is reduced by having a way to enforce that a new version of the software client cannot run against an old version of the service code, which means that the transition that we need to test is:&lt;/p&gt;
&lt;ol&gt;
&lt;li value="1"&gt;Service: Vcurrent&lt;br /&gt;Client: Vcurrent&lt;/li&gt;
&lt;/ol&gt;&lt;ol&gt;
&lt;li value="2"&gt;Service: Vnext&lt;br /&gt;Client: Vcurrent&lt;/li&gt;
&lt;/ol&gt;&lt;ol&gt;
&lt;li value="3"&gt;Service:&amp;nbsp; Vnext&lt;br /&gt;Client: Vnext&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Testing strategies when upgrading multiple services&lt;/p&gt;
&lt;p&gt;Upgrading a single service in the cloud has its own level of complexity, but in practice we are often upgrading multiple services at a time. Common issues during upgrades happen when one service is rolled out sooner or later than expected. It is thus important to be able to build a timeline of the full upgrade to understand the dependencies that one service will have on another. The best would be to be able to replicate this upgrade procedure on a production like environment, then running end to end application tests. However, this is not always easy to coordinate and execute. It is generally easier to list the different versions of the services that we are planning to run against during the upgrade. With this information, we can build a test matrix to ensure that we are clear when running against any of those versions.&lt;/p&gt;
&lt;p&gt;One thing to keep in mind is that upgrade test procedures often rely on moving a test lab back and forth from one version to the other. How easy it is to execute upgrade testing depends entirely on how easy it is to set up a lab environment to a particular state.&amp;nbsp; If you work on a system that is constantly running through upgrades, or has a complex upgrade matrix, investing in easy and quick deployments will be crucial in being empowered to test and find upgrade related issues.&lt;/p&gt;
&lt;p&gt;In conclusion, upgrade testing requires thinking in terms on versions of services and clients, and thinking about the different states that a user may be when the process begins, executes and completes. Upgrade tests are often more involved and sometimes hard to execute; However, they are crucial to ensure that our customers will have a good experience when we offer them the new version of our service. Even if customers may be exposed to the system in upgrade for a small period of time, a small issue can lead to issues like corruption which can cause long term issues. Upgrade testing is often overlooked, because it is hard and because it is transient. However our customers always deserve the highest quality service, and that includes the periods of time when we are upgrading.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Federico Gomez Suarez,&amp;nbsp; Microsoft&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10253765" width="1" height="1"&gt;</content><author><name>Windows Live Tester</name><uri>http://blogs.msdn.com/wltester_4000_hotmail.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>You write too many tests and open too many bugs</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/wltester/archive/2011/12/20/you-write-too-many-tests-and-open-too-many-bugs.aspx" /><id>http://blogs.msdn.com/b/wltester/archive/2011/12/20/you-write-too-many-tests-and-open-too-many-bugs.aspx</id><published>2011-12-20T18:42:25Z</published><updated>2011-12-20T18:42:25Z</updated><content type="html">&lt;p&gt;In my experience, many testers tend to identify with certain types of measurements and metrics which on the surface may seem to be desirable to maximize.&amp;nbsp; These statistics can provide feedback to the tester to indicate that they are making progress and getting something done through the course of their work.&amp;nbsp; However, when one looks below the surface, &amp;ldquo;overachieving&amp;rdquo; within these statistics may in fact be an indicator of an unhealthy software development system.&amp;nbsp; Let&amp;rsquo;s take a look at a couple of tester-related statistics which I believe are worthwhile to scrutinize:&amp;nbsp; Number of Tests, and Number of Bugs Found.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol&gt;
&lt;li value="1"&gt;Number of Tests&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I think many agree it is good to provide regression coverage by authoring stable automated tests &amp;ndash; it provides a way to repeatedly check that the system has not deviated from a well-known &amp;ldquo;good&amp;rdquo; state.&amp;nbsp; As part of the daily job of the SDET, writing test automation is something that most of us do on a regular basis.&amp;nbsp; And heck, if writing one test case to provide coverage is good, then writing 100 cases must be better, right?&amp;nbsp; This line of thought unfortunately seems to be quite common.&amp;nbsp; I have seen multiple instances of testers being proud of the sheer volume of tests they added to the automation system:&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;As part of my feature, I added 450 tests to the BVTs, isn&amp;rsquo;t it great?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Not necessarily :)&amp;nbsp;&amp;nbsp; One should consider the ramifications before claiming that &amp;ldquo;more is always better&amp;rdquo;:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tests written as part of automation suites are usually long-lived and passed down to subsequent owners, and the TCO of each test case is usually (much) greater than the initial cost to author the case.&amp;nbsp; Each test written has maintenance costs that are compounded over the entire lifetime of the test, this includes such items as:&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Triage of test failures&lt;/li&gt;
&lt;li&gt;Changes of test code to accommodate design changes&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Fixing unreliable/unstable test variations&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Reporting test results&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Etc...&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;When multiple tests provide duplicate coverage, the time spent on maintenance of duplicated tests is a sunk cost which prevents that time being spent on other areas with low (or zero) coverage&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;What then should be the tester&amp;rsquo;s goal when writing automation?&amp;nbsp; In my opinion, testers should shoot for the &amp;ldquo;Minimal Maximal Set&amp;rdquo;, which is coined to describe the minimal set of test cases which provide the maximum amount of coverage.&amp;nbsp; If you can generate a set of 2 robust test cases which provides the same amount of coverage as another set of 100, the TCO for the minimal set will likely be far less over the lifetime of the cases and will be net positive in terms of team efficiency.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol&gt;
&lt;li value="2"&gt;Number of Bugs Opened&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Testers find bugs; it is part of their DNA.&amp;nbsp; On the surface, it is great to see testers find many defects that would otherwise make their way to the customer.&amp;nbsp; It is also great to see testers to carry a certain pride in being able to uncover bugs in the process of their work.&amp;nbsp; However, this is again a case of &amp;ldquo;more is [not always] better&amp;rdquo;.&amp;nbsp; Some types of bugs found again and again can indicate intrinsic problems in the way that we develop and test the system.&amp;nbsp; For example, consider the following:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A large quantity of BVT/Pri0 types of defects being found repeatedly can be an indicator that proper defect prevention procedures are not sufficient to catch low hanging fruit before developers check in their new code.&amp;nbsp; In essence, teams should never be in a situation where BVT blockers are happening that could have been easily prevented by a check-in test or code review procedure.&amp;nbsp; We should push to find/prevent issues as early as possible in the software development process as it is the most efficient way to ship a quality product&lt;/li&gt;
&lt;li&gt;A pattern of low quality bugs (for example, a preponderance of "won't fix" or "not repro" bugs) may indicate that the test team is wasting the feature team's time with non-issues.&amp;nbsp; Sometimes this can also indicate that the test team has the wrong priorities in mind when testing the product&lt;/li&gt;
&lt;li&gt;Large numbers of base-case functional bugs found late in the milestone may indicate a disconnect between the functional requirements and assumptions that the test team is making&lt;/li&gt;
&lt;li&gt;Patterns of similar defects being found milestone after milestone can indicate that the feature team is not learning from past mistakes.&amp;nbsp; It can also indicate that proper analysis is not being performed against the defect patterns at the end of the individual milestones in order to prevent the problems from happening again in subsequent milestones&lt;/li&gt;
&lt;li&gt;Categories of bugs being missed may indicate an overall lack of attention to fundamentals like security, stress, performance, globalization, etc.&lt;/li&gt;
&lt;li&gt;&amp;nbsp;Large numbers of integration bugs being found late in the cycle can hint at design problems between intersecting components&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Again, what should be the goal here?&amp;nbsp; While it is a fact that good testers can find lots of bugs, I believe that we should look far beyond the numbers and ask ourselves "What do these bugs tell us about the product?" and "What do these bugs tell us about the way we test the product?"&amp;nbsp; Many folks tend to gravitate towards simple bug statistics because they are easy to measure, but unfortunately they don't tell us much in isolation.&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Only when we look at what the statistics are really telling us can we begin to make meaningful progress...&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;-Liam Price, Microsoft&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10249678" width="1" height="1"&gt;</content><author><name>Windows Live Tester</name><uri>http://blogs.msdn.com/wltester_4000_hotmail.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Just because you can test it doesn’t mean you should</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/wltester/archive/2011/12/13/just-because-you-can-test-it-doesn-t-mean-you-should.aspx" /><id>http://blogs.msdn.com/b/wltester/archive/2011/12/13/just-because-you-can-test-it-doesn-t-mean-you-should.aspx</id><published>2011-12-13T17:59:00Z</published><updated>2011-12-13T17:59:00Z</updated><content type="html">&lt;p&gt;A wise test lead once said to me, &amp;ldquo;do as little as possible while still ensuring quality&amp;rdquo;.&amp;nbsp; He wasn&amp;rsquo;t giving me tips on how to be a slacker&amp;nbsp;=)&amp;nbsp; I think what he wanted to say was there always seems to be more work than there are people so it pays to be as efficient as possible,&amp;nbsp; especially when prolonged testing can hold up shipping a product.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;One thing I&amp;rsquo;ve seen at Microsoft is sometimes the tendency to want to test everything, which isn&amp;rsquo;t a bad thing as long as you don&amp;rsquo;t have to ship =)&amp;nbsp; Hence the title &amp;ndash; &amp;ldquo;just because you can test it doesn&amp;rsquo;t mean you should.&amp;rdquo;&amp;nbsp; If say you have several components on a stack calling each other, it makes sense to just test at the highest layer to automatically get coverage for lower components.&amp;nbsp; Some people also call this end to end testing.&amp;nbsp; When you test each component separately, you may have the following issues:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Duplication of effort.&amp;nbsp; Tests of lower level components doing the same testing as end to end tests.&lt;/li&gt;
&lt;li&gt;You may not be testing a component the way it will be used in the product.&amp;nbsp; For example, your tests call an API passing it X, but the caller in the product will only ever call the API with Y.&lt;/li&gt;
&lt;li&gt;Holes in coverage.&amp;nbsp; Because you&amp;rsquo;re testing components in isolation, you may miss main stream customer scenarios.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;So my recommendation?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Test at the highest layer whenever possible.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;If the top layer is not yet available, then temporarily test the lower layer with the intention that they will be replaced with end to end tests.&lt;/li&gt;
&lt;li&gt;Focus testing on main customer scenarios first taking a top down approach.&amp;nbsp; This maximizes coverage and at the same time focuses on scenarios customers will hit first.&lt;/li&gt;
&lt;li&gt;Use code coverage tools to drill down on coverage of components.&amp;nbsp; If code is not being used by top-level components then question whether the code should be there at all.&lt;/li&gt;
&lt;li&gt;Push devs to do unit testing of their components.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Of course there are times when component testing is called for.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Component code cannot be easily hit by end to end testing.&amp;nbsp; An example is negative&amp;nbsp; or error testing.&lt;/li&gt;
&lt;li&gt;A component is consumed by multiple clients or it's a public API that anybody can consume.&amp;nbsp; In this case you should treat this component as the highest layer.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Performance tests should ideally go through the top layer and each component logs their own performance numbers.&amp;nbsp; But if you want to test things like throughput it might make sense to go through the component directly.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Any testing where going through the top layer would just be too slow or not possible like&amp;nbsp; security testing, stress testing, fault injection, etc.&amp;nbsp; For example, you may need to ensure an app can open 100K different files for fuzz testing but going through the UI would be painfully slow.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;What about MVVM (Model View ViewModel) you say?&amp;nbsp; This is where you have a layer (ViewModel) that encapsulates data and functionality needed by the UI allowing you have to have a very thin UI layer, even making it easy to replace the UI layer if needed.&amp;nbsp; Some folks prefer testing against the ViewModel as opposed to going through the UI.&amp;nbsp; As somebody who has done both, I can tell you that testing against the ViewModel is much easier and UI testing can be a pain.&amp;nbsp; But in my opinion, the easy way is not worth the risk.&amp;nbsp; We saw several bugs slip through because the thin UI layer that supposedly didn&amp;rsquo;t have any bugs of course did.&amp;nbsp; Going through the ViewModel has its uses like expediting certain operations but I don&amp;rsquo;t recommend exclusively testing against it.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;So to close, test end to end first, and component test only if you need to.&amp;nbsp; Lazy testers are efficient testers, unless they&amp;rsquo;re&amp;nbsp; trying to outsource their work on craigslist =)&amp;nbsp; Feel free to comment if you have any thoughts on this topic.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;-Samson Tanrena&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10247281" width="1" height="1"&gt;</content><author><name>Windows Live Tester</name><uri>http://blogs.msdn.com/wltester_4000_hotmail.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Creativity in Testing</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/wltester/archive/2011/12/07/creativity-in-testing.aspx" /><id>http://blogs.msdn.com/b/wltester/archive/2011/12/07/creativity-in-testing.aspx</id><published>2011-12-07T21:55:00Z</published><updated>2011-12-07T21:55:00Z</updated><content type="html">&lt;p&gt;One of the wonderful parts of testing software is that beyond the pure technical aspects of the discipline lie many&amp;nbsp;opportunities&amp;nbsp;for the tester to exercise their creativity in potentially game-changing ways. &amp;nbsp;Although we work in a field where some of the quality assurance tasks are handed down to us from previous owners (legacy test suites, existing test cases, etc.), it is important to note that it is possible to break from the norm and provide real value by using approaches that have never been used before in the areas which we are testing. &amp;nbsp;Sometimes we can see greater gains not from working harder, but by simply thinking differently.&amp;nbsp; Some of this takes courage, as it is hard to differ from some of the time honored approaches.&amp;nbsp; However, as my experience grows in the field, time and time again I find that the testers who distinguish themselves are not afraid to try new techniques and approaches, and are always looking for creative ways to break the product and new ways to improve.&amp;nbsp;&amp;nbsp; Sometimes these new techniques end in failure, and that is ok.&amp;nbsp; Sometimes the new techniques spur on measurable improvements in the ways that we look at and validate the quality of the software.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;There are times when testers are viewed simply as &amp;ldquo;test execution machines&amp;rdquo;, but great value can come out of looking beyond what is scripted or specified and going &amp;ldquo;beyond the tests&amp;rdquo;.&amp;nbsp; What we do is more of an art than a science, and that is what keeps it interesting to me personally.&amp;nbsp; Sometimes it can feel great to hear the words from your teammates "How did you think of doing that?"&amp;nbsp; J&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;What are some ways that you are able to spark your testing creativity and/or find inspiration?&amp;nbsp; Here are a few ideas that we have used in teams that I have worked in.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Randomly pick two features in the same product and look for all intersections between them; test those intersections&lt;/li&gt;
&lt;li&gt;Use the software without a mouse&lt;/li&gt;
&lt;li&gt;Test on extremely low-end hardware or extremely low bandwidth network connection&lt;/li&gt;
&lt;li&gt;Learn from all of your predecessors.&amp;nbsp; Look at old bug reports, you will find a wealth of untapped information and ideas which can help you with new approaches.&amp;nbsp; Also look at reports from unrelated areas&amp;hellip;&lt;/li&gt;
&lt;li&gt;Use the software with your "off" hand&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Take your work outside&amp;nbsp;&amp;nbsp; J&amp;nbsp; Test outside, on your laptop&lt;/li&gt;
&lt;li&gt;Gain inspiration from other disciplines.&amp;nbsp; Sometimes use of creativity in art, music, business, athletics, etc. can help influence creativity and provide a spark in how you go about testing.&amp;nbsp; Research your favorite musicians, athletes, carpenters, humanitarians, and see what inspires them, see what makes them tick.&amp;nbsp; As an example:&amp;nbsp; Jazz musicians will frequently engage in improvisational music in which the instrumentalists feed off of the spontaneous melodies of their band-mates.&amp;nbsp; This same technique can be applied to testing&amp;hellip;get a small group of folks in a room together and have them &amp;ldquo;group-test&amp;rdquo; a product, supplying little structure/guidance to the testing.&amp;nbsp; Allow the testing to bounce from one area to another and see where it takes the group&amp;hellip;sometimes the results can be very interesting&amp;hellip;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Test a feature side-by-side with a competitor's offering&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Go for a quick jog, and brainstorm test cases along the way.&amp;nbsp;&amp;nbsp; You will remember some of them&amp;nbsp; when you get back&amp;nbsp; J&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Use the software for a day with a very large font setting&lt;/li&gt;
&lt;li&gt;Write a test suite which generates data based off of customer interaction patterns, gathered by telemetry&lt;/li&gt;
&lt;li&gt;Artificially constrain your time &amp;ndash; role play the scenario where you only have a single hour to ensure the quality of your feature.&amp;nbsp; What would you test?&amp;nbsp; What would you try?&amp;nbsp; Where would you spend your time?&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Have your children and/or parents try to break the product.&amp;nbsp; Watch them as they use it, and note any usability or functional concerns&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Use the wisdom of others to help test your software.&amp;nbsp; Have a large population of engineers vote on whether particular features work correctly or not.&amp;nbsp; Use this data to target testing deep-dives&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Share with others &amp;ndash; sometimes just talking through some of the more interesting bugs you have encountered with a few folks informally can start important testing collaborations&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Have someone else give you a list of things that are important to them in the software, and then use it as a starting place for your own exploration&lt;/li&gt;
&lt;li&gt;Try model-based testing in an area which has never been tested that way before&lt;/li&gt;
&lt;li&gt;Without looking at specifications, come up with a list of "Ten things that must work" for your feature/area; verify that these things indeed work&lt;/li&gt;
&lt;li&gt;Test someone else's area while they test yours&lt;/li&gt;
&lt;li&gt;Step through the code in the debugger while you are testing a scenario&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Read the code flow itself while you are testing a scenario&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Tape a golf ball to your keyboard (yes, this was done&amp;nbsp; J )&lt;/li&gt;
&lt;li&gt;Test while listening to mariachi (or speed metal, classical, jazz, etc) music&lt;/li&gt;
&lt;li&gt;Etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Comments/Questions are always welcome.&amp;nbsp; &amp;nbsp;Please contribute/share your own examples of inspiration and/or creativity.&amp;nbsp; Thanks for reading!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;-Liam Price, Microsoft&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10245293" width="1" height="1"&gt;</content><author><name>Windows Live Tester</name><uri>http://blogs.msdn.com/wltester_4000_hotmail.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Testing In Production</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/wltester/archive/2011/11/28/testing-in-production.aspx" /><id>http://blogs.msdn.com/b/wltester/archive/2011/11/28/testing-in-production.aspx</id><published>2011-11-28T23:48:18Z</published><updated>2011-11-28T23:48:18Z</updated><content type="html">&lt;p&gt;One of the most useful resources for a test engineer dealing with web services is the production environment. This is the live environment that exposes the product to end users. Some of the challenges that the production environment provides us are the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li value="1"&gt;How do we know that software that works in a developer box or on a test lab will work in a production environment?&lt;/li&gt;
&lt;/ol&gt;&lt;ol&gt;
&lt;li value="2"&gt;What information can we gather from production that will help us release a higher quality product?&lt;/li&gt;
&lt;/ol&gt;&lt;ol&gt;
&lt;li value="3"&gt;How do we detect and react to issues found after a software upgrade?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In this blog post, we will look at some of the strategies that can be used to improve quality by incorporating the production environment and production data into our testing.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Smoke Testing in production&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Some bugs appear more readily in production due to discrepancies between the test and live environments.&amp;nbsp; For example, the network configuration in a test environment might be slightly different from the live site, causing calls between datacenters to fail unexpectedly.&amp;nbsp; One possible way to identify issues like this would be to perform a full test pass on the production environment for every change that we want to make.&amp;nbsp; However, we don't want to require running a full suite of tests before every upgrade in the live environments since this would be prohibitively time-consuming.&amp;nbsp; Smoke tests are a good compromise, as they give us confidence that the core features of the product are working without incurring too high of a cost.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;A &lt;a href="http://en.wikipedia.org/wiki/Smoke_testing"&gt;smoke test&lt;/a&gt; is a type of test that performs a broad and shallow validation of the product. The term comes from the electronics field, where after plugging in a new board, if smoke comes out, we cannot really do any more testing. During daily testing, we can use smoke tests as a first validation that the product is functional and ready for further testing.&amp;nbsp; Smoke tests also provide a quick way to determine if the site is working properly after deploying an update.&amp;nbsp; When we release an update to our production environment we generally perform the following steps to validate that everything went as planned:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol&gt;
&lt;li value="1"&gt;Prior to updating the site, we run some tests against the current version.&amp;nbsp; Our goal is to make sure that the system is healthy and our tests are valid before starting the upgrade.&lt;/li&gt;
&lt;/ol&gt;&lt;ol&gt;
&lt;li value="2"&gt;We then update a subset of the production site. Preferably, this portion will not be available to end users until we complete the smoke test.&lt;/li&gt;
&lt;/ol&gt;&lt;ol&gt;
&lt;li value="3"&gt;Next, we run the tests against the updated portion of the site. It is important to have clarity on which version the tests are running against. We should have a clean pass of the smoke tests before we proceed.&amp;nbsp; If we encounter problems, we can compare the results pre- and post- upgrade to help focus the troubleshooting investigation.&lt;/li&gt;
&lt;li&gt;Continue the rollout to the rest of the production environment.&lt;/li&gt;
&lt;/ol&gt;&lt;ol&gt;
&lt;li value="5"&gt;Finally, run the tests again to validate the entire site is working as expected.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The tests used for smoke testing should have the following qualities:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol&gt;
&lt;li value="1"&gt;Smoke tests need to be very reliable, as a false positive may cause either unnecessary false alarms or a loss of trust in the smoke test suite.&lt;/li&gt;
&lt;li&gt;Smoke tests need to be very fast.&amp;nbsp; The main point of smoke testing is quickly identify problems, and long running tests can either delay updates to the site, or potentially allow users to access buggy code before the tests catch it.&lt;/li&gt;
&lt;li&gt;Smoke tests need to be good at cleaning up after running. We need to avoid having test data mixed in with real customer data since tests can potentially create data that isn&amp;rsquo;t intended to be processed in production.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Windows Live uses an automated smoke test tool which is able to do a validation of the service within a few minutes. The same utility is used in developer boxes, test environments and production, and is consistently updated as new features are added to the system.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Reacting to issues through data collection and monitoring&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Even though we may have done thorough functional validation, shipping a new feature to production always implies a risk that things may not work as intended.&amp;nbsp; Logging and real-time monitoring are tools that help us in this front.&amp;nbsp; Before shipping a new feature to production, try to answer the following questions. This will give you a sense of readiness for handling issues:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol&gt;
&lt;li value="1"&gt;How will you know that users are having issues with the feature?&amp;nbsp; Will you mostly rely on user feedback, or will you be able to detect and measure failures yourself? Will the people running the site be able to tell something is wrong?&lt;/li&gt;
&lt;/ol&gt;&lt;ol&gt;
&lt;li value="2"&gt;If a user raises an issue, what are the resources that you will have available to investigate? Will you require the user to collect detailed logs?&lt;/li&gt;
&lt;/ol&gt;&lt;ol&gt;
&lt;li value="3"&gt;In the event of an issue, are your test libraries prepared for quickly building up a test scenario based on a user's feedback?&amp;nbsp; The ability to craft tests based on logs and the user&amp;rsquo;s repro steps generally indicates how long it will take for someone to reproduce the issue and validate a fix, which has a direct impact on the time to resolution.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Some of the strategies that windows live uses &amp;nbsp;for allowing quicker reaction to issues are the following:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol&gt;
&lt;li value="1"&gt;We allow user initiated log collection, both on the client and on the server side. Taking the product group out of the critical path when collecting data saves the team a significant amount of time and effort.&lt;/li&gt;
&lt;li&gt;We support using the user logs to craft tests for reproducing an issue. Our tools take logs, remove any actual reference of the users data contents, and replay the traffic.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Using production data as input for tests&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The involvement of Test in production should be limited to releasing a new feature or investigating an issue. Production contains a wealth of data that helps us better define what to test. The higher priority tests are those that map to the core customer calling patterns, and for existing scenarios, production data is the best source. Some of the interesting questions that production data analysis is able to answer are the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li value="1"&gt;What are the different kinds of users in the environment? What are the characteristics that identify them?&lt;/li&gt;
&lt;li&gt;What are the most common calling patterns? Which ones most frequently cause errors?&lt;/li&gt;
&lt;li&gt;Do the site&amp;rsquo;s traffic patterns indicate changes in user behavior?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Gathering and analyzing data to answer the above and other questions is often non-trivial, but the resulting data is invaluable, particularly when deciding which areas should have a bigger focus when testing.&lt;/p&gt;
&lt;p&gt;Within Windows Live, we have used this approach to understand both user scenarios and calling patterns. We measure some of the characteristics of the data (like how many folders a SkyDrive has, or how many comments photos typically have) to identify both common scenarios and outliers. This data lets us focus efforts like performance testing and stress on the most common scenarios, while ensuring that we have coverage on the edge cases.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;When using production data in testing, the approach to privacy is extremely important and needs to be figured out before starting the work. Our tools only interact with abstractions of user data, with all actual user content and identity removed. We care about what the data looks like, not specifically what the data is.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;In conclusion, the effectiveness of a test engineer can be enhanced by using production as a source of information. It may be by making sure that all the core scenarios work as expected through smoke testing, by creating a quick mechanism for reacting to issues, or by harvesting data to feed into test tools and plans.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;References&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;[1] &lt;a href="http://en.wikipedia.org/wiki/Smoke_testing"&gt;http://en.wikipedia.org/wiki/Smoke_testing&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10242199" width="1" height="1"&gt;</content><author><name>Windows Live Tester</name><uri>http://blogs.msdn.com/wltester_4000_hotmail.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Object Model Design</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/wltester/archive/2011/11/14/object-model-design.aspx" /><id>http://blogs.msdn.com/b/wltester/archive/2011/11/14/object-model-design.aspx</id><published>2011-11-14T18:34:29Z</published><updated>2011-11-14T18:34:29Z</updated><content type="html">&lt;p&gt;Recently I was asked my opinion on creating object models for automated UI software testing &amp;ndash; do I prefer LFM or POM? There is no right or wrong answer here &amp;ndash; because I own a framework for automating Web UI, I&amp;rsquo;ll speak to this topic from that perspective. POM (Physical Object Model) style models expose the controls on the page and abstract away the details of how those controls are implemented. LFM (Logical Functional Model) style models expose methods that automate the actions the user can take and abstract away all of the details of how those actions are performed. Here is a concrete example that shows how one would write a test case to initiate a search on Bing&amp;rsquo;s home page:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;LFM Style:&lt;/p&gt;
&lt;p&gt;Logical.Bing.Search(&amp;ldquo;Michael Cartwright&amp;rdquo;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;POM Style:&lt;/p&gt;
&lt;p&gt;Physical.Bing HomePage.SearchTextBox.Text = &amp;ldquo;Michael Cartwright&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Physical.Bing HomePage.SearchButton.Click();&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I feel that the &amp;ldquo;best&amp;rdquo; object models expose both &amp;ndash; what do I mean by &amp;ldquo;best?&amp;rdquo; The notion of best must start with the idea that the best object models are the ones that maximize the number of real product bugs found while minimizing the &amp;ldquo;cost.&amp;rdquo;&amp;nbsp; What are the major &amp;ldquo;costs&amp;rdquo; of an object model? There is:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Cost of an Object Model&lt;/p&gt;
&lt;p&gt;1. Up-front cost of writing the model&lt;/p&gt;
&lt;p&gt;2. Updating the model as the product changes&lt;/p&gt;
&lt;p&gt;3. Writing test cases that use the model&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The object models that minimize cost over time minimized all three costs - it is cheap to create them, keep them updated as the product changes, and its also cheap to write tests.&amp;nbsp;&amp;nbsp; One approach to achieving this end is to first expose POM style controls classes that encapsulate all of the controls on a page.&amp;nbsp; Once all controls are automatable, take any actions that are taken in more than 1 test case and create a LFM style action-based method for that action.&amp;nbsp; The method will internally use the POM style controls so that&amp;nbsp; there is not code duplication. So what does this look like?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;// A class to enable automating the BING home page&lt;/p&gt;
&lt;p&gt;public class BingHomePage&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;// A method that will execute a search.&amp;nbsp; Multiple test cases perform&lt;/p&gt;
&lt;p&gt;// this action, so we wrap it into a re-usable method&lt;/p&gt;
&lt;p&gt;public void Search(string searchString)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;this.SearchTextBox.Text = searchString;&lt;/p&gt;
&lt;p&gt;this.SearchButton.Click();&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;// All of the controls on the Bing home page&lt;/p&gt;
&lt;p&gt;public HtmlTextBox SearchTextBox { get; set; }&lt;/p&gt;
&lt;p&gt;public HtmlButton SearchButton { get; set; }&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;How does this minimize cost over time?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;2 ways:&lt;/p&gt;
&lt;p&gt;1. No duplication of code&lt;/p&gt;
&lt;p&gt;a. The two steps required to search are in one place - inside of the Search() method in the BingHomePage class&lt;/p&gt;
&lt;p&gt;b. The code for finding the Search text box occurs in one place - its inside of the SearchTextBox property in the class BingHomePageControls&lt;/p&gt;
&lt;p&gt;2. Resilient to product changes&lt;/p&gt;
&lt;p&gt;a. If the search text box location changes, the only object model change will be to the controls class where the text box is defined. The test cases and action methods in the model will remain unchanged.&lt;/p&gt;
&lt;p&gt;b. If the steps required to perform a search change, but the controls on the page do not change, then the tester will only need to update the body of the &amp;ldquo;Search&amp;rdquo; method, and all test cases using this method will remain unchanged.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Conclusion&lt;/p&gt;
&lt;p&gt;While I know that there is no &amp;ldquo;right way&amp;rdquo; to write object models, I&amp;rsquo;ve used this style of model in the past and it served us well.&amp;nbsp; It was our approach to eliminate duplication of code.&amp;nbsp; The rule of thumb we followed was to use the reusable LFM style methods for any actions occurring more than once, and use the POM controls for 1-off actions that only occur once. There is significant cost in creating and maintaining this style of model but in my experience it minimizes long term maintenance cost my minimizing code duplication. Recently teams have been exploring ways to generate the controls classes in an automated way, saving tons of time. Please leave comments on this post as I would love to hear what style of object model your team uses, and what you think about this style.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Michael&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Lots of good info in this post came from &lt;a href="http://www.teknologika.com/blog/category/watin/"&gt;http://www.teknologika.com/blog/category/watin/&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10236915" width="1" height="1"&gt;</content><author><name>Windows Live Tester</name><uri>http://blogs.msdn.com/wltester_4000_hotmail.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Playback Testing Using Log files</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/wltester/archive/2011/11/07/playback-testing-using-log-files.aspx" /><id>http://blogs.msdn.com/b/wltester/archive/2011/11/07/playback-testing-using-log-files.aspx</id><published>2011-11-07T22:36:19Z</published><updated>2011-11-07T22:36:19Z</updated><content type="html">&lt;p&gt;&lt;b&gt;Author&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Vijay Upadya, vijayu@microsoft.com&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Abstract&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Most testers are familiar with record/playback testing. A variation of this approach is log playback testing. Instead of explicitly recording the user actions using a recorder, this technique simply relies on the information in the log file produced by the system under test to play back the scenario. This is extremely useful for reproducing issues reported by customers which are typically hard to reproduce otherwise due to lack of detailed repro steps. This approach also lends itself well to creating data driven tests and can be used to augment the existing test automation.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Testing and investigating failures in a non-deterministic software system can be very costly and painful. In most cases the only source of information to know what code path got exercised are the log files produced by the application. This paper talks about how the information in log files can be used to playback the sequence of actions to test specific code paths and also reproduce bugs. We will look at exploring an extension of this approach and how log files can be used as a source for data driven testing by simply varying the sequencing of actions that are played back. This paper illustrates the technique using real a world example. Finally the paper discusses the benefits and how it can be applied to different test domains.&lt;/p&gt;
&lt;ol&gt;&lt;/ol&gt;
&lt;p&gt;&lt;b&gt;1.&amp;nbsp; &lt;/b&gt;&lt;b&gt;Introduction&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Log files are typically used for diagnosing issues reported by users of the product. In most cases log analysis is done manually where developers read the log and try to understand the sequence of events happening during the failure and where it went wrong. For catastrophic failures like crashes the call stack will mostly suffice in figuring out the issue in the product. But when there are functional failures, having a detailed log will go a long way in helping diagnose the issue quickly.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now we can take it further and design logging with the intent of generating logs for easy auto analysis and use it to actually playback the scenario as it happened in user&amp;rsquo;s machine.&amp;nbsp; In order for this to be successful, the logging format needs to be designed right from the beginning of the product cycle with playback in mind.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Log files are also a great source of information that shed light on how customers are using the product and information contained in them can be sourced as test cases that test teams can then run regularly during their test passes.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;In the next sections we will discuss how log files can be used for playback and more exhaustive testing. We will use an example of &lt;a href="http://en.wikipedia.org/wiki/File_synchronization"&gt;file synchronization software&lt;/a&gt;&lt;a href="file:///C:/Users/vijayu/Documents/pnsqc2011_paper_logPlaybackTesting.doc#_edn1"&gt;&lt;sup&gt;[i]&lt;/sup&gt;&lt;/a&gt; for the discussion.&lt;/p&gt;
&lt;ol&gt;&lt;/ol&gt;
&lt;p&gt;&lt;b&gt;2.&amp;nbsp; &lt;/b&gt;&lt;b&gt;Information needed for playback&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/b&gt;&lt;/p&gt;
&lt;p&gt;In general log files for the application contain sequence of important events that happen along with information about data. Let us explore characteristics of a good log that is &amp;lsquo;playback ready&amp;rsquo;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;There are two main pieces of information needed for playback&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;User intent (i.e., scenario user intended to accomplish)&lt;/li&gt;
&lt;li&gt;Path taken by product in fulfilling this intent (i.e., product's execution flow)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;User Intent&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;i&gt;User intent&lt;/i&gt; is about capturing what a user intended to do while using the product. It could be a simple task or a series of tasks as part of a larger scenario.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;User performing mathematical operations on a series of numbers in a calculator application&lt;/li&gt;
&lt;li&gt;User copying photos from camera to local folder on his PC and syncing it to other PCs using file synchronization software.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;A log file needs to provide enough information to make it possible to interpret the user intent.&amp;nbsp; There are two items of interest for capturing user intent&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Timeline of actions performed by user&lt;/li&gt;
&lt;li&gt;Data passed to each of these actions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;For simple applications like a calculator, just capturing user intent will probably suffice as the component behaves in a deterministic manner for a given input. For example, user presses 2 + 4= and calculator produces 6. The calculation logic is synchronous and execution flow deterministic. However for non-deterministic software like file synchronization where there are a number of threads executing in an asynchronous manner, and where the order of operations are not guaranteed, just capturing user intent is not enough. We need an additional piece of data &amp;ndash; the path taken by the product or execution flow.&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Product Path&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;i&gt;Path taken by the product&lt;/i&gt;: When a user performs a specific task, the product itself will perform a series of tasks to accomplish the user intent. These tasks are typically implemented in multiple components and some of these could be executed in parallel.&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;There are two items of interest for capturing product path&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Timeline of states and their transitions while executing tasks&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Information on any concurrent execution of tasks&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;How to capture user intent&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In general, in order to capture user intent the product needs to understand general user actions or entry points to the application. This would be happening in any functional product. For example, when a user presses &amp;lsquo;+&amp;rsquo; in a calculator application, the application will &amp;lsquo;interpret&amp;rsquo; it as an addition (user intent). In most cases it&amp;rsquo;s just a matter of logging this information at appropriate locations in the product where it &amp;lsquo;understands&amp;rsquo; the user intent. The timeline is also an important piece of data that enables determining the ordering of operations happening in the product and helps identify any concurrent operations happening. The product needs to log the timestamp information indicating when this action occurred along with any relevant data passed.&lt;/p&gt;
&lt;ol&gt;&lt;/ol&gt;
&lt;p&gt;&lt;b&gt;4.&amp;nbsp; &lt;/b&gt;&lt;b&gt;How to capture the product path&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;This involves thinking through control flow of the product while realizing the user intent and would involve logging different state changes and their transitions. Again here timestamp information needs to be logged along with data. More on this is discussed in the next section with an example.&lt;/p&gt;
&lt;ol&gt;&lt;/ol&gt;
&lt;p&gt;&lt;b&gt;5.&amp;nbsp; &lt;/b&gt;&lt;b&gt;How to playback&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;There are two things that need to be played back - one is the user intent and the other is the control flow of the application. For simple applications, just playing back the user intent (using the same data and in the same order) would help in replaying the scenario and reproducing the bugs. However for more complex products that are non-deterministic in nature (meaning, for the same scenario it could take a slightly different code path due to its asynchronous nature) the product path also needs to be 'played back&amp;rsquo; so that it converges on the path that caused failure in the user scenario.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take an example of file synchronization software. There are three main operations that users of this application typically perform &amp;ndash; Creation, Updates and Deletion (CUD) of files and folders. Now these can happen in any order at any time on any number of files on any number of devices that are enabled for sync. The product need to understand each of these main user gestures (CUD) and it&amp;rsquo;s easy for it to log when it happens.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Looking into the control flow of typical file synchronization software while performing these CUD operations reveals that it comprises of the following sub-operations&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;i&gt;Scanning&lt;/i&gt; for detecting changes,&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Uploading&lt;/i&gt; (file to cloud storage),&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Downloading&lt;/i&gt; (file on another machine) and&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Realizing &lt;/i&gt;(copying)&lt;i&gt; &lt;/i&gt;the file downloaded to right folder location so that the file appears on disk on other machine.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Some of these operations can happen in parallel asynchronously (for example, uploading and downloading).&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s say a user reported a &amp;lsquo;failure to sync&amp;rsquo; issue and shared the log file which looks something like this (only relevant portion shown for illustration purposes) with the log format &amp;lsquo;TIME_STAMP&amp;rsquo;&amp;nbsp; &amp;lsquo;TASK&amp;rsquo;&amp;nbsp; &amp;lsquo;Data&amp;rsquo;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;06-14-2011 00:08:46.507 SCANNER: thread for 'C:\Users\vijayu\SyncFolder' started&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;06-14-2011 00:08:46.617 SCANNER: FILE_ACTION_ADDED for 'C:\Users\vijayu\SkyDrive\ myPhoto1.jpg&amp;rsquo;&lt;/p&gt;
&lt;p&gt;06-14-2011 00:08:48.703 SCANNER: thread finished scanning&lt;/p&gt;
&lt;p&gt;..&lt;/p&gt;
&lt;p&gt;06-14-2011 00:08:49.826 DOWNLOADIN file &amp;lsquo;myPhoto2.jpg&amp;rsquo;&lt;/p&gt;
&lt;p&gt;06-14-2011 00:08:49.827 UPLOADING file 'C:\Users\vijayu\SyncFolder\myPhoto1.jpg&amp;rsquo;&lt;/p&gt;
&lt;p&gt;..&lt;/p&gt;
&lt;p&gt;06-14-2011 00:08:51.626 DOWNLOADIN file &amp;lsquo;myPhoto2.jpg&amp;rsquo;&lt;/p&gt;
&lt;p&gt;06-14-2011 00:08:51.629 UPLOADING file 'C:\Users\vijayu\SyncFolder\myPhoto1.jpg&amp;rsquo;&lt;/p&gt;
&lt;p&gt;..&lt;/p&gt;
&lt;p&gt;06-14-2011 00:08:53.322 DOWNLOADIN file &amp;lsquo;myPhoto2.jpg&amp;rsquo;&lt;/p&gt;
&lt;p&gt;06-14-2011 00:08:53.327 UPLOADING file 'C:\Users\vijayu\SyncFolder\myPhoto1.jpg&amp;rsquo;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;From the above log snippet it&amp;rsquo;s easy to figure out that a new file myPhoto1.JPG was added, picked up by scanner and it&amp;rsquo;s trying to upload it. Also it&amp;rsquo;s trying to download a different file myPhoto2.JPG (on a different thread) at around the same time. Also this looks like the point of failure as log contains repeated section of the above uploading/downloading sequences. This might be an indication of the application getting into some kind of infinite loop and the issue surfaces only when upload and download happens simultaneously. This can happen when user has added files on both machine1 and machine2 and each is making its way onto the other machine. On the machine where failure is happening, the upload and download are occurring simultaneously resulting in some kind of a failure.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;So to summarize we have following information:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;User intent: Addition of file on two machines and syncing to all machines&lt;/li&gt;
&lt;li&gt;Product path: Scanning completed, Simultaneous download and upload task started&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now for playing it back, the playback tool needs to detect these two pieces of information. From the line on scanning along with file name it&amp;rsquo;s straightforward to interpret that the user added a new file myPhoto1.jpg and this condition can easily be reproduced by adding a new file to the path specified.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The lines in log on downloading tasks along with file names indicate that there was newly added file on the other machine that it&amp;rsquo;s trying to download to this machine (where failure occurred). So to simulate this condition, the tool needs to add a file to a different machine to the path specified.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Examining the timestamp for upload and download indicates that these two tasks are happening (nearly) simultaneously. Putting it all together, these are the steps playback tool need to perform&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create file myPhoto1.jpg in machine1&lt;/li&gt;
&lt;li&gt;Create file myPhoto2.jpg in machine2&lt;/li&gt;
&lt;li&gt;Wait for download to start for file myPhoto2.jpg&lt;/li&gt;
&lt;li&gt;As soon as download starts, also start uploading myPhoto1.jpg&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;User intent actions can easily be reproduced by adding a new file to the path specified on machine1 and machine2. However controlling the flow to ensure download and upload occurs simultaneously is a little tricky.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;In order to accomplish this control over flow of execution our team used the &lt;a href="http://research.microsoft.com/en-us/projects/detours/"&gt;detours&lt;/a&gt;&lt;a href="file:///C:/Users/vijayu/Documents/pnsqc2011_paper_logPlaybackTesting.doc#_edn2"&gt;&lt;sup&gt;[ii]&lt;/sup&gt;&lt;/a&gt; library. In a nutshell the detours library enables hijacking function calls in the product and gives test code a chance to control its execution timings. The way this is used in the example case for file synchronization mentioned above is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a test binary that detours upload and download functions by providing a detour function&lt;/li&gt;
&lt;li&gt;Load this test binary to the product process&lt;/li&gt;
&lt;li&gt;In the upload detour function wait until download is ready to&amp;nbsp; begin&lt;/li&gt;
&lt;li&gt;In the download detour function wait until upload is ready to&amp;nbsp; begin&lt;/li&gt;
&lt;li&gt;When the condition is met, continue the execution&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;How it can be used for test generation&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The test team could use this playback technique to pro-actively identify issues before releasing the product. This can be achieved by taking an existing log for a given scenario (say produced by functional tests), interpreting the log to identify different states in the product and simulating all possible control flow conditions.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;For example, in the above file sync case, on creating a file to sync folder we noted that product goes through four states. From this we can come up with the following three cases that can occur simultaneously:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Download during Scanning&lt;/li&gt;
&lt;li&gt;Download during Uploading&lt;/li&gt;
&lt;li&gt;Download during Realizing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The same playback tool can then be used to simulate the above three conditions and test the products behavior.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The log playback has the potential to make reproduction of issues less painful and cheaper. It does require initial investment to come up with the infrastructure for playback, but once it&amp;rsquo;s in place, it can rapidly enable test teams to test different conditions/code paths the product could take and also to reproduce issues reported by the users.&lt;/p&gt;
&lt;ol&gt;&lt;/ol&gt;
&lt;p&gt;&lt;b&gt;8.&amp;nbsp; &lt;/b&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="file:///C:/Users/vijayu/Documents/pnsqc2011_paper_logPlaybackTesting.doc#_ednref1"&gt;&lt;sup&gt;[i]&lt;/sup&gt;&lt;/a&gt; &lt;a href="http://en.wikipedia.org/wiki/File_synchronization"&gt;http://en.wikipedia.org/wiki/File_synchronization&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="file:///C:/Users/vijayu/Documents/pnsqc2011_paper_logPlaybackTesting.doc#_ednref2"&gt;&lt;sup&gt;[ii]&lt;/sup&gt;&lt;/a&gt; Galen Hunt and Doug Brubacher.&lt;i&gt; &lt;/i&gt;&lt;a href="http://research.microsoft.com/pubs/68568/huntusenixnt99.pdf"&gt;&lt;i&gt;Detours: Binary Interception of Win32 Functions&lt;/i&gt;&lt;/a&gt;&lt;i&gt;, &lt;/i&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Calibri; font-size: small;" face="Calibri" size="3"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10234781" width="1" height="1"&gt;</content><author><name>Windows Live Tester</name><uri>http://blogs.msdn.com/wltester_4000_hotmail.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Old World vs. New World</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/wltester/archive/2011/10/31/old-world-vs-new-world.aspx" /><id>http://blogs.msdn.com/b/wltester/archive/2011/10/31/old-world-vs-new-world.aspx</id><published>2011-10-31T16:58:06Z</published><updated>2011-10-31T16:58:06Z</updated><content type="html">&lt;p&gt;As software has become increasingly more complex and the demands placed on the test discipline have escalated, it is clear that the legacy approaches for testing software are not always adequate.&amp;nbsp; Sometimes test teams get caught up in performing the same types of tests and/or taking the same types of approaches not because those things keep providing great value, but oftentimes simply because &amp;ldquo;that&amp;rsquo;s the way it has always been done&amp;rdquo; J.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Years ago, as part of thinking about this phenomenon with a colleague, we drew up a small &amp;nbsp;playbook which described the values that our test team &amp;ldquo;aspired to&amp;rdquo;.&amp;nbsp; As a small part of this was the below &amp;ldquo;Old World, New World&amp;rdquo; chart which tried to summarize some of the tenets of what we were trying to move towards (and some of the stuff we were trying to move away from&amp;hellip;). &amp;nbsp;We wanted to take a hard look at some of the things that we were investing a good deal of time into and see if we could make any tweaks to get more bang for the buck.&amp;nbsp; Looking at the chart now it is interesting for me to see that many of the points are still relevant and we still haven&amp;rsquo;t met all of our goals&amp;hellip;but some incremental progress has been made J&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s look at the chart and then briefly comment on some of the bullet points:&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;table border="1" cellspacing="0" cellpadding="0" valign="top"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;Old World&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;New World&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;Doing same old testing that we have always done (grandfathered in)&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;Killing old tests, procedures, efforts, etc. that have little value or whose value does not measure up to the cost&lt;/li&gt;
&lt;li&gt;Expanding /adding tests with creative additions&lt;/li&gt;
&lt;li&gt;Exploratory/Scenario testing investments&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;Test spending time running regression tests on private binaries&lt;/li&gt;
&lt;li&gt;Test adding coverage on new functionality&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;Having Developers run regressions using centralized system&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Test adding coverage on new functionality&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;Spending time triaging regression results because of test issues&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;Spending time getting tests to 100% in all configurations&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;3-4 week Full Test Pass&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;1 week Full Test Pass&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;Adding, Adding, Adding, Adding&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;Removing, Removing, Innovating, Adding&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;Classical SDET&amp;rdquo; deliverables are rewarded&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;Radical thinking and results are rewarded&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;Finding bugs after check-in&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;Finding bugs before check-in&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;Test serving Development&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;Test serving Quality&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Doing same old testing that we have always done (grandfathered in)/Killing old tests, procedures, efforts&amp;hellip;.&amp;rdquo;:&amp;nbsp; &amp;nbsp;The idea behind this row is as was described above, i.e. test teams frequently keep doing the same old things again and again without analysis of the return on investment for some of these tasks.&amp;nbsp; As an example one of my test teams maintained an extremely large and complex test suite which tested a particular type of authentication behavior.&amp;nbsp; This test suite had thousands upon thousands of variations and was not particularly stable.&amp;nbsp; Analysis showed that the maintenance costs for the test suite were quite high and in fact the suite was not catching many regressions and/or finding new issues (certainly not enough to justify its existence).&amp;nbsp; The decision was made to retire the old test suite (at least from regular automated runs) and replace it with a much more simplified version which was stable and which provided similar coverage.&amp;nbsp; Although changing something like this was scary, in the long run it was the right thing to do for the team.&amp;nbsp; The end result was that due to the reduction in maintenance costs, the testers who previously owned the suite were able to spend more time on end-to-end scenario testing and ad-hoc testing and as a result were able to catch more defects from reaching the customer.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Test spending time running regression tests on private binaries&amp;hellip;/Having Developers run regressions using centralized system.&amp;rdquo;:&amp;nbsp;&amp;nbsp; When at all possible, centralized systems should be put into place in such a way that the test team is not a bottleneck for development.&amp;nbsp; Instead of developers tossing the binaries to test over the fence and waiting for the test team&amp;rsquo;s &amp;ldquo;blessing&amp;rdquo;, a centralized system which can be leveraged by everyone across the disciplines can enable developers to verify their private binaries and protect against regressions.&amp;nbsp; In the meantime, test can be off tracking down the tough bugs J&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Spending time triaging regression results because of test issues/Spending time getting tests to 100% in all configurations&amp;rdquo;: &amp;nbsp;In my estimation, there is no greater drain in an SDET&amp;rsquo;s work life than unstable automation.&amp;nbsp; When SDETs spend too much time triaging test automation bugs, it takes away from high value work such as moving quality upstream or finding hard-to-track-down bugs in end to end flows.&amp;nbsp; The &amp;ldquo;Golden Standard&amp;rdquo; that our test teams try to evangelize is that every time a test fails, it should be an indicator of an actual product bug.&amp;nbsp; While this is sometimes difficult to achieve in practice, it is certainly a good result to aspire to.&amp;nbsp; Another problem with unstable automation is that it causes a loss of credibility within the work group.&amp;nbsp; Unstable tests and/or false alarms reduce our clout as testers and may cause the &amp;ldquo;Boy who cried wolf&amp;rdquo; syndrome in which people simply stop being alarmed when tests fail.&amp;nbsp; Apathy like this in the team is dangerous.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;3-4 week Full Test Pass/1 week Full Test Pass&amp;rdquo;: &amp;nbsp;This speaks to the results that a test team can realize when they tighten up their battery of automation by increasing the stability of their test automation and removing tests/procedures which no longer provide benefit.&amp;nbsp; These particular numbers came from a test team which worked on a component which had a huge number of system interdependencies, so please treat the particular example with a grain of salt J.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Adding, Adding, Adding, Adding/Removing, Removing, Innovating, Adding&amp;rdquo;:&amp;nbsp; &amp;nbsp;&amp;nbsp;The trap of continuously adding is something that I have encountered in multiple test teams that I have worked in and is a fairly common occurrence.&amp;nbsp; When a new feature comes along, tests are added.&amp;nbsp; When a test hole is uncovered, tests are added.&amp;nbsp; When a new test technique is researched, tests are added.&amp;nbsp; The problem with this approach is that every new test/process/procedure that is added has a cost, and that cost is compounded over its lifetime.&amp;nbsp; This creates a maintenance burden that becomes unmanageable.&amp;nbsp; Thankfully there are many ways out of the trap.&amp;nbsp; One example is to enforce review and removal of old test variations which are no longer relevant at the same time that new tests are added.&amp;nbsp; &amp;nbsp;Another example is to figure out ways to combine/consolidate test cases such that coverage is maximized with a minimal set of tests.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;ldquo; &amp;rsquo;Classical SDET&amp;rsquo; deliverables are rewarded/Radical thinking and results are rewarded&amp;rdquo;: &amp;nbsp;Along the same lines as the comments above about questioning the same old testing that was grandfathered in, it is important for SDETs to feel safe that they can try new techniques to augment or potentially replace some of these old approaches.&amp;nbsp; This requires management to be &amp;ldquo;on board&amp;rdquo; with SDETs who are able to see past the cloudy veil of the past, &amp;nbsp;and take risks (with the expectation that some of these risks will fail).&amp;nbsp; We will never escape from the past if we are not receptive to innovation and the risk that comes with it.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Finding bugs after check-in/Finding bugs before check-in&amp;rdquo;:&amp;nbsp; &amp;nbsp;&amp;nbsp;Although testers are frequently characterized by the issues that they raise while testing the actual product (i.e., after the code has made its way into the build after check-in), the most efficient time to find the bugs is before the code makes its way into the build and ideally before a single line of code has been written.&amp;nbsp; This is all part of the &amp;ldquo;Push Quality Upstream&amp;rdquo; war cry.&amp;nbsp; There are many ways to go about this and each method probably deserves its own series of blog posts J:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ensuring test is plugged into the design and spec phase&lt;/li&gt;
&lt;li&gt;Test actively involved in pre check-in code inspection&lt;/li&gt;
&lt;li&gt;Creating a check-in battery of tests which are run automatically before the new code is committed to the source control, and whose failure will prevent the code from being checked in&lt;/li&gt;
&lt;li&gt;Etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Test serving Development/Test serving Quality&amp;rdquo;:&amp;nbsp; &amp;nbsp;&amp;nbsp;Sometimes the test discipline is seen as a henchman for the development discipline, with test waiting ready for development to throw the code over the fence.&amp;nbsp; It is important for test to assert that the master we are serving is quality and that may not always include being the safety net for development.&amp;nbsp; For example, sometimes it means teaching development to be their own safety net J&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Future blog posts will dive deeper into the above shifts in behavior as well as describing some of the processes that can be used to facilitate the transitions.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Comments/Questions are always welcome.&amp;nbsp; Thanks for reading!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;-Liam Price, Microsoft&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10231747" width="1" height="1"&gt;</content><author><name>Windows Live Tester</name><uri>http://blogs.msdn.com/wltester_4000_hotmail.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Code Inspection for SDETs, Part II</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/wltester/archive/2011/10/24/code-inspection-for-sdets-part-ii.aspx" /><id>http://blogs.msdn.com/b/wltester/archive/2011/10/24/code-inspection-for-sdets-part-ii.aspx</id><published>2011-10-25T00:59:00Z</published><updated>2011-10-25T00:59:00Z</updated><content type="html">&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;In part I of this series, we looked at some of the benefits of the SDET discipline being fully plugged into the code inspection pipeline.&amp;nbsp; These benefits include such outcomes as pushing quality upstream and raising SDET awareness of the code that is being tested.&amp;nbsp; Plus, it&amp;rsquo;s fun!&amp;nbsp; &lt;/span&gt;J&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Now we will share the general process and approach that we take in one of our SDET Code Inspection virtual teams.&amp;nbsp; Please note that the format and style of the code inspection process described below may differ from what you are familiar with (especially if you have used a formal code review process in the past).&amp;nbsp; We participate in a type of lightweight group review, which takes bits and pieces from several formal inspection processes.&amp;nbsp; Also, please note that the approach being outlined below is for post-check-in inspections in which we are able to review code on a larger scale across multiple components (as opposed to pre-check-in inspections which tend to be narrower and focused more around particular isolated changes).&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&lt;b&gt;Ownership&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;As often as possible, we push to have the SDET who owns the feature area also own and drive the end-to-end code inspection process for that area.&amp;nbsp; This is helpful in several ways, such as helping reinforce ownership of the area, introducing more SDETs to the process, and also in getting the SDET owner to think about questions like:&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;What materials/specs/information should I provide to the participants of the review in order for them to gain an understanding of the feature that is being reviewed?&amp;nbsp;&amp;nbsp; Am I able to distill the essence of the feature and describe this to the participants? &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;What are the most critical pieces of code to review?&amp;nbsp; Oftentimes, we must scale back the review in order to meet our maximum lines-of-code guidelines.&amp;nbsp; It is a worthwhile exercise for SDETs to be able to make qualitative judgments about what code area are riskier and what code requires more attention&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&lt;b&gt;Setting Up the Meeting&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;In general, the feature test owner will do the following prior to the review meeting:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Calibri; font-size: small;" face="Calibri" size="3"&gt;1.&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Decide what code will be reviewed&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Usually 1500-2000 lines-of-code is optimal for a one hour review meeting.&amp;nbsp; Anything more than that is counter-productive, and is unlikely to be finished in a single review meeting.&amp;nbsp; Sometimes multiple review meetings are needed depending on the size/complexity of the feature.&amp;nbsp; Smaller features can sometimes be reviewed completely in an hour.&amp;nbsp; Other features may require multiple meetings (3, 4, 5+) to cover all of the critical code&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Areas of code to review are decided upon at least 3-4 days in advance and are clearly stated (included files(s), line numbers, etc) in the meeting invite.&amp;nbsp; To allow for SDETs to work at their own pace, it is important to give them several days to complete the review&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;It is oftentimes useful for the code selection process to be a collaborative effort between the disciplines to figure out which are the most critical areas to review&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style="font-family: Calibri; font-size: small;" face="Calibri" size="3"&gt;2.&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Decide upon supporting materials&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Additional materials can/should be provided in order to inform the reviewers about the feature(s) under review.&amp;nbsp; This can include functional/design/test specifications or a non-technical synopsis of what the code is trying to do.&amp;nbsp; It is amazing how useful this can be during the inspection process, as we have seen numerous bugs come out of reviews where the only thing wrong with the code was that it wasn&amp;rsquo;t doing what the spec said it should be!&amp;nbsp; &lt;/span&gt;J&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;It is important that all reviewers provide feedback using the same process so that folks are on the same page (both literally and figuratively) during the actual review meeting.&amp;nbsp; In some cases, this &amp;nbsp;means that physical printouts using a common tool are made for all members who will participate in the review.&amp;nbsp; In other cases, this means that an online tool will be leveraged to provide feedback.&amp;nbsp; Whatever the process is, it should be consistent for all reviewers and designated by the test owner.&amp;nbsp; Otherwise, you run into confusion over exactly what lines-of-code are being discussed at particular times during the review meeting.&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style="font-family: Calibri; font-size: small;" face="Calibri" size="3"&gt;3.&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Send out the meeting request&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;The meeting request goes out to all members of the code inspection virtual team as well as other members of the feature area&amp;rsquo;s crew&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;The meeting request includes the code to be reviewed as well as any supporting materials&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&lt;b&gt;Reviewing the Code&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;In this post, I won&amp;rsquo;t dive into the mechanics of reviewing the code (this will be covered in its own future post).&amp;nbsp; In our inspection process, the actual heads-down inspection happens offline at the reviewer&amp;rsquo;s pace, and this happens before the code review meeting occurs.&amp;nbsp; Reasons for this approach include:&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;This allows for different styles/paces of review to take place&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;This provides more time during the actual meeting to discuss the defects and other potential problems&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&lt;b&gt;The Meeting&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;As mentioned above, in our process the meeting itself is not where the inspection takes place, but rather where the defects are tabulated and discussed.&amp;nbsp; In general this is accomplished during the meeting by moving through the code, page by page, and recording the defects and which participants found them.&amp;nbsp; Since one of our main goals in this process is education, in many cases we try to take the time to talk about particular patterns of defects found in the code and how these might be avoided altogether with a holistic approach.&amp;nbsp; We also spend some time talking about the design decisions that were made as well as interdependencies between features, as this is a common area where defects tend to crop up.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;During the review meeting, the feature test owner owns ensuring that:&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Calibri; font-size: small;" face="Calibri" size="3"&gt;1.&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;The meeting keeps moving and does not stall over incidental discussions&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Calibri; font-size: small;" face="Calibri" size="3"&gt;2.&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;All defects/comments are recorded&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Calibri; font-size: small;" face="Calibri" size="3"&gt;3.&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Any open issues or unclear areas are noted&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&lt;b&gt;The Aftermath&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;After the meeting is completed, the feature test owner owns:&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Calibri; font-size: small;" face="Calibri" size="3"&gt;1.&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Opening bugs and/or work items to ensure that the issues are tracked to completion&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Calibri; font-size: small;" face="Calibri" size="3"&gt;2.&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Following up on any open issues uncovered during the review.&amp;nbsp; Sometimes particular areas of the code need more discussion and/or research before the issue is considered completely understood.&amp;nbsp; All issues marked for follow-up during the review should be driven to closure by the feature test owner&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Calibri; font-size: small;" face="Calibri" size="3"&gt;3.&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Providing a summary of the review to the Code Inspection virtual team, including data about the area reviewed and the issues found&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&lt;b&gt;Tracking Statistics&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;We keep running totals of various types of data from the review sessions.&amp;nbsp; In general, we look at the following statistics/metrics across multiple reviews and multiple areas&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Areas of code reviewed&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Total lines-of-code reviewed per area&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Number of issues found (total yield)&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Issue efficiency (#bugs resolved fixed)/(total yield)&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Special &amp;ldquo;High Impact&amp;ldquo; bucket bugs &amp;ndash; such as security bug yield&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;At the end of particular milestones, we look at the overall statistics and may alter the approach based on the data.&amp;nbsp; In addition, we will frequently provide &amp;ldquo;post mortem&amp;rdquo; feedback to the feature team of particular areas if there are coding/design patterns that the code review team deems to be pervasive enough to warrant special attention.&amp;nbsp; For example, if memory leaks due to a particular coding style/convention are running rampant in &amp;nbsp;a given area, it is helpful to provide feedback to the feature team about the ways in which these types of leaks could be addressed via a slight coding practice adjustment.&amp;nbsp; These suggestions can then be rolled up into development coding guidelines, and in some cases incorporated into static analysis tools.&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;In a future post in this series, we will discuss some of the guidelines that we use during the review of the code in order to make for an efficient and &amp;ldquo;high-yield&amp;rdquo; inspection.&amp;nbsp; Thanks for reading!&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;-Liam Price, Microsoft&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10229602" width="1" height="1"&gt;</content><author><name>Windows Live Tester</name><uri>http://blogs.msdn.com/wltester_4000_hotmail.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Code Inspection for SDETs, part I</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/wltester/archive/2011/10/04/code-inspection-for-sdets-part-i.aspx" /><id>http://blogs.msdn.com/b/wltester/archive/2011/10/04/code-inspection-for-sdets-part-i.aspx</id><published>2011-10-04T22:23:07Z</published><updated>2011-10-04T22:23:07Z</updated><content type="html">&lt;p&gt;(Note for those unfamiliar with the acronym, SDET stands for Software Design Engineer in Test.&amp;nbsp; In simple terms an SDET is an engineer who develops code to test software)&lt;/p&gt;
&lt;p&gt;Code inspection has historically been a &amp;ldquo;high-yield for low cost&amp;rdquo; bug-prevention or bug-detection approach.&amp;nbsp; This is especially true when used as part of formal code review process and integrated into the software development lifecycle.&amp;nbsp; In the multiple teams and companies I have worked at it has been very common for the developers to practice a peer code review system before every check-in, and periodically review entire features post code-complete.&amp;nbsp; However, it has not been common for the test discipline to be fully plugged into the code inspection pipeline, which is less than ideal.&lt;/p&gt;
&lt;p&gt;Here are some examples of the benefits realized with the test discipline participating in the code inspection of the code that they test.&amp;nbsp; Let&amp;rsquo;s walk through a few of them.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Motivation&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;1)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;Knowledge Growth&lt;/b&gt;:&amp;nbsp; Code inspection is an excellent way for testers to become more familiar with the code base that they own from a quality perspective.&amp;nbsp; As we move into a world which requires more technical horsepower and understanding from SDETs, there is really no substitute for having deep code knowledge of the components that they own.&amp;nbsp; In addition, it is a great way for &amp;nbsp;SDETs to uncover test holes and lesser-known functionality in their components.&amp;nbsp; A strategy to grow SDETs into senior roles has to include some level of in-depth code knowledge improvement, and code inspection is a great way to attain that knowledge&amp;nbsp;&lt;/p&gt;
&lt;p&gt;One common concern about testers using code inspection techniques is that the tests that they author will somehow become extremely reliant on implementation details and become fragile and brittle when confronted with product code implementation changes.&amp;nbsp; This is a valid concern and is something to consider.&amp;nbsp; Testers should be careful that they do not rely too much on underlying implementation when designing automation for regression testing for example.&amp;nbsp; On the other hand, knowing current interdependencies and contracts between portions of the product can teach SDETs about what portions of the code may warrant additional testing attention&lt;/p&gt;
&lt;p&gt;2)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;Efficient Defect Prevention:&lt;/b&gt;&amp;nbsp; Root Cause Analysis of various defects has shown that many high priority bugs could have been effectively found and/or prevented through code review or static analysis.&amp;nbsp; In some cases, the best test tool for the job is going through the code itself.&amp;nbsp; Certain classes of bugs can be found quite easily through inspection, for example:&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;br /&gt;Cleanup and logic errors in failure conditions&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;Misuse of certain APIs&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;Broken API contracts&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;Some types of security issues&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;Stylistic coding issues which have long term time drain in terms&lt;br /&gt;of maintainability&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;Etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;3)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;Time Savings:&lt;/b&gt;&amp;nbsp; A wonderful side effect of having a low cost bug finding approach is that it frees SDETs up to do other more time-consuming testing.&amp;nbsp; After all, we are not being paid to be test execution machines.&amp;nbsp; When we find certain classes of bugs more quickly and with less effort, we can move on to tracking down the really difficult bugs through other sophisticated techniques&amp;nbsp;&lt;/p&gt;
&lt;p&gt;4)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;Constant Feedback Loop:&lt;/b&gt;&amp;nbsp; After the code inspection process has been followed for some time on a codebase, certain types of patterns emerge from the various reviews.&amp;nbsp; Many of these defect patterns could be avoided by simply evangelizing how particular defects could be avoided at the code level.&amp;nbsp; &amp;nbsp;As part of the process, these defect patterns can be communicated to the development team as part of coding guidelines which will also prevent future occurrences.&amp;nbsp; Participating in this feedback loop is empowering and provides great value&amp;nbsp;&lt;/p&gt;
&lt;p&gt;5)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;Eliminating Classes of Defects via Tools:&lt;/b&gt;&amp;nbsp; Concentrated effort at code inspection pushes quality upstream and can help multiple teams, division, or company-wide.&amp;nbsp; Working with static analysis tool teams to help identify certain classes of defects and being able to feed that logic into the tools themselves can have a huge impact downstream by preventing the bugs from ever seeing the light of day in the first place&amp;nbsp;&lt;/p&gt;
&lt;p&gt;6)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;Beginner Impact:&lt;/b&gt;&amp;nbsp; Even new code reviewers can make statistically significant impact.&amp;nbsp; Some engineers shy away from doing code inspection because they feel that they need to be a seasoned expert in order to get anything out of it.&amp;nbsp; This couldn&amp;rsquo;t be further from the truth &amp;ndash; studies have shown that although experts at code review do find more bugs than novices, the delta between these two groups is not large and should not discourage folks from participating&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Goals&lt;/b&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;While building our SDET Code Inspection virtual team in my group, we wanted to avoid having a single-minded emphasis on finding defects (although we do encounter numbers of defects).&amp;nbsp; We wanted to also think about the education aspect and the defect prevention aspect as well.&amp;nbsp; Along those lines we concentrate on the following goals:&amp;nbsp;&lt;/p&gt;
&lt;p&gt;1)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Find bugs earlier in the development cycle and push quality upstream&amp;nbsp;&lt;/p&gt;
&lt;p&gt;2)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Increase SDET awareness of the code that is being tested so that more educated decisions can be made with respect to test coverage, test investments, test prioritization, etc.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;3)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Lower the bar of entry into code inspection.&amp;nbsp; Learn techniques and approaches from others&amp;nbsp;&lt;/p&gt;
&lt;p&gt;4)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Provide general code quality feedback per area and feature in order to raise the quality bar&lt;/p&gt;
&lt;p&gt;After every milestone I review our progress towards these goals and tweak the process if needed.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Upcoming blog entries will cover the exact process that we follow in my code inspection team and some examples of the types of defects that can be found through code inspection techniques.&amp;nbsp; Thanks for reading!&amp;nbsp;&lt;/p&gt;
&lt;p&gt;-Liam Price, Microsoft&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10220069" width="1" height="1"&gt;</content><author><name>Windows Live Tester</name><uri>http://blogs.msdn.com/wltester_4000_hotmail.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Hello world!</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/wltester/archive/2011/09/13/hello-world.aspx" /><id>http://blogs.msdn.com/b/wltester/archive/2011/09/13/hello-world.aspx</id><published>2011-09-13T18:39:00Z</published><updated>2011-09-13T18:39:00Z</updated><content type="html">&lt;p&gt;We are the senior SDETs (Software Engineer in Test) at Windows Live in Microsoft.&amp;nbsp; We plan to use this blog to make our voices heard regarding anything and everything test related.&amp;nbsp; So stay tuned for some interesting articles coming your way.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10210113" width="1" height="1"&gt;</content><author><name>Windows Live Tester</name><uri>http://blogs.msdn.com/wltester_4000_hotmail.com/ProfileUrlRedirect.ashx</uri></author></entry></feed>