Yesterday during my Office Hours I chatted with Eric Jacobson about a number of things, but one of them was about how to avoid having to login/logout every single time a test method executes. I normally do login every time for isolation of execution, but we followed the thought process through. The way to handle this desirement is login in the setup phase and then ensure that all your test methods start and stop at the same place. But that of course means that you trust both the authors to remember that and that your scripts will never do anything unexpected and so be able to navigate back. And neither of those are really safe bets. What we can do in this case is exploit the fact that a lot of runners have multiple layers of setup and teardown; test, class, session.

While C# isn’t my normal language, it is the one Eric is using along with the built-in Visual Studio runner so I’m going to bastardize some syntax for it. (I don’t know if this will compile…)

<pre lang="csharp">using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TestNamespace
{
   [TestClass()]
   public class MySetupClass
   {
      [AssemblyInitialize()]
      public static void AssemblyInit(TestContext context)
      {
         /// Runs once before all test methods; login to system here
      }
      
      [AssemblyCleanup()]
      public static void AssemblyCleanup()
      {
         /// Runs once after all test methods; logout of system here
      }
   }
}
<pre lang="csharp">using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TestNamespace
{
   [TestClass()]
   public class SomethingTest
   {

      [ClassInitialize()]
      public static void ClassInit(TestContext context)
      {
         /// Runs once before all test methods in this class
      }

      [ClassCleanup()]
      public static void ClassCleanup()
      {
         /// Runs once after all test methods in this class
      }

      [TestInitialize()]
      public void Initialize()
      {
         /// Runs before each test method in this class; check whether you are on the desired
         /// page, and if not, navigate to it
      }

      [TestCleanup()]
      public void Cleanup()
      {
         /// Runs after each test method in this class
      }

      [TestMethod()]
      public void DoSomethingTest()
      {
         /// This is your actual test method as the attribute implies
      }
   }
}

This level of nesting isn’t often illustrated very clearly int he documentation of the runner which is all the more reason to spend an afternoon with the docs and see what other useful gems are hidden in there.