Many tests need some form of setup action or data before you get rolling in to the test.In a good functional test you want that setup action abstracted away from the UI—having your browser run around creating setup data is slow and brittle!
For example, a test retrieving a user from a system shouldn’t first drive the system around to create that user. The action of creating the user for the real portion of the test should fall to some sort of a backing API. That API might call a web service, stored procedure, or even a command line utility. (Which is exactly what I do as a quick workaround in this test within the Telerik Demo Application’s test suite!)
Using some form of support infrastructure to handle these sorts of setup tasks keeps your tests faster and much less brittle.
A slight variation on this would be the need to load up a baseline dataset. I’m a huge fan of baseline datasets for more complex testing scenarios. A good baseline dataset (also called a “truth set”) helps you ensure you’re getting accurate results in complex scenarios. Think about all the crazy amount of data you need for reliably testing business intelligence or reporting applications.
Obviously these sorts of datasets take up a lot of time and effort to build, so you want to leverage them in a smart way for your tests.
Both of these tasks are easily accomplished in Test Studio!
First, let’s deal with setup for a specific test. If you’re familiar with unit testing frameworks you may understand the concept of a fixture setup method. These methods run once before any other tests in that fixture (class). We can do this same thing in Test Studio via a coded step at the start of a test.
Let’s run with my example above retrieving a user and validating their info displays correctly. I need a way to create that user first, so I’m going to create a separate test to handle that. I can then use that test elsewhere as needed!
The action of the setup is simply via a coded step. Once you’re in code you can do whatever you like: hit a web service, hit a support framework you’re building, or invoke a command line app to handle it for you.
Here’s what that test would look like with a single coded step invoking sqlite3.exe to insert a record in to my sample app. Yes, this is a bit ugly, but it gets done what I need, and it’s the lowest friction route for my environment. Your environment will be different. Do what’s right for your team!
Now let’s reference this support test in the actual test we’ll be using. That’s done by inserting this test as a step in our other test, then completing the various actions we’ll need.
There you have it: a reliable, abstracted and maintainable way to handle setup data for your test.
Keep in mind that I’m creating data; however, I could be performing system configuration, moving files around, or any number of other tasks. The point is I define these things in one place and never let the individual tests work directly with that. This way it’s easy for me to push that work off to a helper API at some later point if I need to.
Baseline data setup can be done in much the same way: create a separate test with a coded step. In that coded step handle your load method. This may be a SQL restore, some import, whatever your system needs.
Next you’ll use that as the first test to run in your defined test list where you need your data loaded:
If you need teardown functionality you can approach it in the same way: create separate tests, use coded steps in those tests, and apply as needed.
Remember: you don’t have to do the required function directly in those tests’ coded steps – by all means you should consider building up some sort of support or backing API/framework to help you handle these sorts of tasks. Don’t build it too quickly, let it evolve and build only what you need as you go.