Automating VMware with VIX
As for many pieces of software, one of the issues in testing TWAPI is the number of different platform configurations under which the test suites need to be run. Manual configuration is tedious and error-prone so automation of the process using VMware and the vix package is a big win.
The Problem
Several aspects lead to a combinatorial explosion in the number of test configurations.
- The operating system, starting with Windows XP and up to Windows 8.1/Windows Server 2012 R2
- 32- and 64-bit versions of each
- Service packs, which need to be tested separately because of differences in DLL exports
- Tcl version 8.5 and 8.6
- Multiple TWAPI distribution formats
- Application suites (needed for testing some TWAPI functionality)
Even after triage, a significant number of combinations remain. For each configuration, the appropriate Tcl and TWAPI versions have to be loaded, test scripts run and results gathered.
This is where VMware and the Tcl vix package can be used to automate the process.
The Solution
The first step is setting up VMware virtual machines running the different versions of the operating system. I use VMware Workstation for testing but any VMware product can be used including the free VMware Player and VMware Server products. If using a product that supports virtual machine snapshots, you can make a snapshot corresponding to each service pack and save some disk space. For products like VMware Player which do not have the snapshots capability, separate virtual machines are needed for each service pack.
The above is a one time set up. Once that is done, test runs can be executed at any time, iterating through each configuration in turn. Each test cycle in the run then
- Starts the appropriate virtual machine (VM) from a known state
- Copies the selected Tcl version, TWAPI distribution and test harness to the target VM
- Runs the test scripts, collecting and storing test results
- Resets the VM to a known state so that persisted machine state changes do not carry over to the next test run
Each of these steps involves controlling the target VM in some fashion. VMware provides the VIX API for the purpose. We will make use of this via the Tcl vix package. Note that because this package is based on COM interfaces, it will only run on Windows host systems though the target VM may run any operating system.
The Demonstration
We will demonstrate the use of VIX through a sample tclsh
interactive session. Of course, a real test harness will wrap these steps in a script. This session assumes you have the vix package installed as described in its documentation.
Starting the VM
We start off by loading the vix package, initializing it and connecting to the local VMware Workstation host. Because this matches the package defaults we do not need to specify any additional options.
% package require vix
0.4
% vix::initialize
% vix::Host create host
::host
Having connected to the host, we open the virtual machine of interest. In the case of VMware Workstation, the machine is identified by the path to its VMX file.
% set vm [host open "c:/virtual machines/vm0-xpsp3/vm0-xpsp3.vmx"]
::oo::Obj81::guest#1
It is a good idea to always start a test run with a clean slate so we revert the VM to a previously created snapshot called Base
.
% set snap [$vm get_snapshot Base]
::oo::Obj111
% $vm revert_to_snapshot $snap
% $snap destroy
We can then power up the VM. One thing to keep in mind when working with VMware VIX interface is that many commands depend on VMware tools to be running in the target VM. So after the VM starts up, we wait for the tools to finishing loading. Depending on the host system this can take a little time so we wait for up to a minute.
% $vm power_on
% $vm wait_for_tools 60
Logging into the target VM
It has been straighforward so far but we now run into our first roadblock. Some TWAPI modules implement commands related to window management and the desktop. Testing these modules therefore requires a login session at the console and unfortunately there is no way to create one automatically with VMware. If there is a desktop already running, we can run programs in it but there is no way to create one.
Thus we have to manually log in to the VM (not shown here) before continuing with our next step. We assume we have done that here.
As an aside, the above is not strictly true because one can reduce security settings in the target VM so that manual logins are not necessary. I am loathe to lower security though even on test VM's.
Once we have manually logged into the console of the target VM, we return to our tclsh
session to proceed with logging in through VMware as well. Because we want to interact with the desktop, we need to make sure we use the same account to login as we used for manually logging into to the target VM console.
% $vm login tester myunguessablepassword -interactive 1
Copying files
We can now start off copying the files needed for testing. We will store everything under the c:\testdir
directory. Note the various commands for file and directory management and transfer.
We begin recreating the directory structure and copying a single file Tcl executable that we use for testing.
% $vm rmdir c:/testdir
% $vm mkdir c:/testdir/bin
% $vm copy_to_vm tclkit-cli-8.6.3-x86.exe c:/testdir/bin/tclkit-cli.exe
The file name is not valid
Oops. It turns out that VMware's VIX implementation will accept /
as path separators in some commands but not others. Changing the path separator to \
(escaping it for Tcl's benefit) fixes the issue. You could also have of course used the file nativename
to transform the path.
% $vm copy_to_vm tclkit-cli-8.6.3-x86.exe c:\\testdir\\bin\\tclkit-cli.exe
The same command will also copy entire directory trees, and we use it to copy the twapi distribution of choice and test scripts.
% $vm mkdir c:/testdir/lib
% $vm copy_to_vm twapi-bin c:\\testdir\\lib\\twapi-bin
% $vm copy_to_vm ../tests c:\\testdir\\tests
We are now ready to run our test scripts.
Running tests on the target VM
Running program on the target VM is very straightforward. For example,
% $vm exec c:/windows/system32/notepad.exe -activatewindow 1
2684 0 0
The above would start notepad on the desktop and return its PID. The -activewindow
option ensures the window is not iconized on start up.
We could use this method to run TWAPI's test suite wrapper but for pedagogical purposes, we will do things slightly differently. We will invoke our Tcl interpreter and pass it an inline script and wait for it to return.
% $vm script c:/testdir/bin/tclkit-cli.exe {
cd c:/testdir/tests
lappend auto_path c:/testdir/lib
package require tcltest
package require twapi
tcltest::configure -outfile results.txt
source base.test
exit 0
} -wait 1
2608 0 11
% $vm read_file c:\\testdir\\tests\\results.txt
base.test: Total 456 Passed 435 Skipped 21 Failed 0
...remaining lines skipped...
In a real test driver, we would have used $vm copy_from_vm
instead of $vm read_file
to collect the results and store to a local file.
We are done with target VM and can shut it down and clean up.
% $vm shutdown
% $vm destroy
% host destroy
% vix::finalize
The test runner script can now move on to repeating the sequence with the next configuration.
In Conclusion
Even if tests are fully scripted, (re)configuring the target platforms can still be a hindrance to running tests on a continuous basis. Automation using virtual machines is relatively simple to implement and removes much the tedium from the process. (Those not on Windows hosts can look at the vmrun
program included by VMware as an alternative to the Tcl vix package albeit somewhat more inconvenient to program.)