5

During my UnitTest, I am creating data that needs to be referenced in future UnitTests. For example:

[TestMethod]
public void CreateOrder()
{
    Order order = new Order();
    int orderNumber = order.Create();
    // return orderNumber;
}

[TestMethod]
public void ProcessOrder()
{
    int orderNumber = (int)TestContext.Properties["OrderNumber"];
    ProcessOrder(orderNumber);
}

I need to save off 'orderNumber' so that another UnitTest (possibly on another agent) can use this generated order. I have decided that I can use a database, but then I have to operate it like a queue in removing items, and would prefer not to go that route.

Is there any way to 'return' the orderNumber back to the LoadTest and pass that in as a Context parameter in a call to another UnitTest?

esac
  • 24,099
  • 38
  • 122
  • 179
  • Can you explain why you need the exact instance created by the other test? Why is it not sufficient to create the instance in a setup method and be used by both tests? – unholysampler Jun 03 '13 at 16:53
  • You have one method that creates orders. This method operates at a faster rate than processing. You have to prove that you can create 40000 orders in 1 hour, and at the same time, process those order (you don't have to process all 40K orders, just prove that while processing is happening, you can create 40K orders). You can't just create all 40K to begin with, because there are concurrency issues that could come up by creating and processing at the same time. You cant do a Create/Process/Create/Process pattern either as you won't get through all 40K orders. The order HAS to exist to process. – esac Jun 03 '13 at 17:47
  • I haven't done any work with Load Tests, so I can't give direct help. But if the idea is that both of those methods are regularly called as a way to "create load", then it might be as simple as having a `Queue` member variable in the class these methods are defined in. That way, `CreateOrder()` can add to the queue and `ProcessOrder()` can pull from it. Otherwise, try read [this](http://msdn.microsoft.com/en-us/library/ms182561%28v=vs.80%29.aspx) for details about Load Tests in Visual Studio. – unholysampler Jun 03 '13 at 20:26
  • Unfortunately with a LoadTest, creating it in the Class would create it PER agent. So the queue on Agent 1 would be a different queue than agent 2. This wouldn't work as I am creating a fixed number of orders. It would have to be done in the LoadTest Plugin and passed into the UnitTest, and have the UnitTest pass it back. – esac Jun 03 '13 at 21:57
  • Can you clarify how agents fit into this scenario in your question? What do you mean by `The LoadTest Plugin`? Is there a specific plugin for this that you are using? – Ryan Gates Jun 12 '13 at 20:21
  • Easy solution would be to save each created order in a static variable ConcurrentBag/Dictionary. However, since this class is created on each LoadTest agent, this would not be shared across agents. I only mentioned the LoadTest plugin because it is how data is passed from the loadtest to the unittest via the TestContext. – esac Jun 13 '13 at 04:23

1 Answers1

4

You can do it via a LoadTest Plugin and using the UserContext. Each virtual user has his own UserContext and you can use it to pass/retrieve data from TestContext.

  1. Create a load test plugin
  2. Add event handlers on the TestStarting & TestFinished events. The TestStarting event will fire before the TestInitialize method and the TestFinished after the TestCleanup:

    public void TestStarting(object sender, TestStartingEventArgs e)
    {
        // Pass the UserContext into the TestContext before the test started with all its data retrieved so far data.
        // At the first test it will just be empty
        e.TestContextProperties.Add("UserContext", e.UserContext);
    }
    
    public void TestFinished(object sender, TestFinishedEventArgs e)
    {
        // do something with the data retrieved form the test 
    }
    
  3. Use the TestInitialize & TestCleanup to get/add data from/to UserContext:

    [TestInitialize]
    public void TestInitialize()
    {
        // Get the order number which was added by the TestCleanup method of the previous test
        int orderNumber = (int) UserContext["orderNumber"];
    }
    
    [TestCleanup]
    public void TestCleanup()
    {
        // When the CreateOrder test is completed, add the order number to the UserContext
        // so the next will have access to it
        UserContext.Add("orderNumber", orderNumber);
    }
    
  4. To get access to the UserContext on the test add the following property on every UnitTest:

    public LoadTestUserContext UserContext
    {
        get
        {
            return TestContext.Properties["$LoadTestUserContext"] as LoadTestUserContext;
        }
    }
    
  5. In you load test configuration set Test Mix Model = Based on sequential order so your tests will be executed in the order you add them on the Test Mix.

Note: For this to work, you have to add each TestMethod on a single UnitTest file. If you have them at the same file, the TestInialize and TestCleanup methods will be executed on every TestMethod contained, and possibly you will try to access data that you don't have (e.g. trying to get the orderNumber on CreateOrder).

chaliasos
  • 9,659
  • 7
  • 50
  • 87
  • 1
    Hi , I working step by step with your answer and it's ok , but on step 4 I didn't success to retrive 'TestContext.Properties' parameter because it abstract and no static parameter , You can help ? – Hadash Jan 14 '15 at 10:19