Automating console (CLI) applications (Windows)

Last edited on

Overview

Even though Squish focuses on automating GUI applications it is possible to do some limited testing of console applications by using cmd.exe and some small workarounds.

It is important to note that recording key presses is not possible when using cmd.exe as application under test (AUT); however, you can send key presses to it via type():

type("{type='Window'}", "<Return>")

Let's imagine that we have the following simple batch file mycommand.bat:

@echo off

echo What is your name?
echo.
set _input= 
set /p _input=? 

echo.
echo Hello %_input%.
echo.

echo How old are you, %_input%?
echo.
set _input= 
set /p _input=? 

echo.
echo Really?! Sorry, I had no idea!
echo.

echo Do you want to proceed?
echo.
set _input= 
set /p _input=?
mycommand.bat

To test this we can write a Squish test script which automates the following via the type() command and other functionality in Squish:

Here is such a test script written in Python:

import os
import os.path
import sys

def main():
    # The 'program' variable holds the name of the AUT
    # including its full path by making use of the
    # squishinfo.testCase property which holds the test
    # case's folder name. It assumes that the AUT is
    # in the test suite folder (i.e., the folder above
    # the test case).
    program = squishinfo.testCase + "\\..\\mycommand.bat"

    # Start cmd.exe
    start_cmd_exe()

    # Ensure a simple prompt:
    type("{type='Window'}", "prompt $G ")
    type("{type='Window'}", "<Return>")

    # Clear screen
    type("{type='Window'}", "cls")
    type("{type='Window'}", "<Return>")

    # Path to script must be adjusted, and the
    # "expected" value, too
    type("{type='Window'}", program)
    type("{type='Window'}", "<Return>")
    expected = "\r\n> <PROGRAM>\r\nWhat is your name?\r\n\r\n?"
    actual = get_text_from_cmd_window()
    actual = actual.replace("\r\n> " + program, "\r\n> <PROGRAM>")
    test.compare(expected, actual)

    # Enter name "John"
    type("{type='Window'}", "John")
    type("{type='Window'}", "<Return>")
    expected = "\r\n> <PROGRAM>\r\nWhat is your name?\r\n\r\n? John\r\n\r\nHello John.\r\n\r\nHow old are you, John?\r\n\r\n?"
    actual = get_text_from_cmd_window()
    actual = actual.replace("\r\n> " + program, "\r\n> <PROGRAM>")
    test.compare(expected, actual)

    # Enter age "21"
    type("{type='Window'}", "21")
    type("{type='Window'}", "<Return>")
    expected = "\r\n> <PROGRAM>\r\nWhat is your name?\r\n\r\n? John\r\n\r\nHello John.\r\n\r\nHow old are you, John?\r\n\r\n? 21\r\n\r\nReally?! Sorry, I had no idea!\r\n\r\nDo you want to proceed?\r\n\r\n?"
    actual = get_text_from_cmd_window()
    actual = actual.replace("\r\n> " + program, "\r\n> <PROGRAM>")
    test.compare(expected, actual)

def start_cmd_exe():
    aut = "cmd"
    path = os.path.join(os.environ["WINDIR"], "system32")
    registerAUT(aut, path)
    startApplication('"' + aut + '" /c start /wait cmd.exe')

def get_text_from_cmd_window():
    mouseClick(waitForObject("{type='Window'}"), 17, 18, MouseButton.LeftButton)
    type("{type='Window'}", "<Up>")
    type("{type='Window'}", "<Up>")
    type("{type='Window'}", "<Up>")
    type("{type='Window'}", "<Return>")

    type("{type='Window'}", "<Down>")
    type("{type='Window'}", "<Down>")
    type("{type='Window'}", "<Down>")
    type("{type='Window'}", "<Return>")

    type("{type='Window'}", "<Return>")

    ctx_prev = currentApplicationContext()

    aut = "notepad"
    path = os.path.join(os.environ["WINDIR"], "system32")
    registerAUT(aut, path)
    startApplication('"' + aut + '"')

    type(waitForObject("{type='Window'}"), "<Ctrl+V>")
    snooze(1)
    t = waitForObject("{type='Edit'}").text
    type(waitForObject("{type='Window'}"), "<Ctrl+Z>")
    type(waitForObject("{type='Window'}"), "<Alt+F4>")

    setApplicationContext(ctx_prev)
    return t

def registerAUT(aut, path, squishserver_host=None, squishserver_port=None):
    s = '"' + os.environ["SQUISH_PREFIX"] + '/bin/squishrunner"'
    if squishserver_host is not None:
        s += ' --host ' + squishserver_host
    if squishserver_port is not None:
        s += ' port=' + str(squishserver_port)
    s += ' --config addAUT "' + aut + '" "' + path + '"'
    if sys.platform == "win32" and s.endswith('"'):
        s = '"' + s
    os.system(s)
test.py

Other implementations

JavaScript:

function main()
{
    // The 'program' variable holds the name of the AUT
    //including its full path by making use of the
    // squishinfo.testCase property which holds the test
    // case's folder name. It assumes that the AUT is
    // in the test suite folder (i.e., the folder above
    // the test case).
    program = squishinfo.testCase + "\\..\\mycommand.bat";

    // Start cmd.exe
    start_cmd_exe();

    // Ensure a simple prompt:
    type("{type='Window'}", "prompt $G ");
    type("{type='Window'}", "<Return>");

    // Clear screen
    type("{type='Window'}", "cls");
    type("{type='Window'}", "<Return>");

    // Path to script must be adjusted, and the
    // "expected" value, too
    type("{type='Window'}", program);
    type("{type='Window'}", "<Return>");
    expected = "\r\n> <PROGRAM>\r\nWhat is your name?\r\n\r\n?";
    actual = get_text_from_cmd_window();
    actual = actual.replace("\r\n> " + program, "\r\n> <PROGRAM>");
    test.compare(expected, actual);

    // Enter name "John"
    type("{type='Window'}", "John");
    type("{type='Window'}", "<Return>");
    expected = "\r\n> <PROGRAM>\r\nWhat is your name?\r\n\r\n? John\r\n\r\nHello John.\r\n\r\nHow old are you, John?\r\n\r\n?";
    actual = get_text_from_cmd_window();
    actual = actual.replace("\r\n> " + program, "\r\n> <PROGRAM>");
    test.compare(expected, actual);

    // Enter age "21"
    type("{type='Window'}", "21");
    type("{type='Window'}", "<Return>");
    expected = "\r\n> <PROGRAM>\r\nWhat is your name?\r\n\r\n? John\r\n\r\nHello John.\r\n\r\nHow old are you, John?\r\n\r\n? 21\r\n\r\nReally?! Sorry, I had no idea!\r\n\r\nDo you want to proceed?\r\n\r\n?";
    actual = get_text_from_cmd_window();
    actual = actual.replace("\r\n> " + program, "\r\n> <PROGRAM>");
    test.compare(expected, actual);
}

function start_cmd_exe()
{
    aut = "cmd";
    path = OS.getenv("WINDIR") + "\\System32";
    registerAUT(aut, path);
    startApplication('"' + aut + '" /c start /wait cmd.exe');
}

function get_text_from_cmd_window()
{
    mouseClick(waitForObject("{type='Window'}"), 17, 18, MouseButton.LeftButton);
    type("{type='Window'}", "<Up>");
    type("{type='Window'}", "<Up>");
    type("{type='Window'}", "<Up>");
    type("{type='Window'}", "<Return>");

    type("{type='Window'}", "<Down>");
    type("{type='Window'}", "<Down>");
    type("{type='Window'}", "<Down>");
    type("{type='Window'}", "<Return>");

    type("{type='Window'}", "<Return>");

    ctx_prev = currentApplicationContext();

    aut = "notepad";
    path = OS.getenv("WINDIR") + "\\System32";
    registerAUT(aut, path);
    startApplication('"' + aut + '"');

    type(waitForObject("{type='Window'}"), "<Ctrl+V>");
    snooze(1)
    t = waitForObject("{type='Edit'}").text;
    type(waitForObject("{type='Window'}"), "<Ctrl+Z>");
    type(waitForObject("{type='Window'}"), "<Alt+F4>");

    setApplicationContext(ctx_prev);
    return t;
}

function registerAUT(aut, path, squishserverHost, squishserverPort)
{
    var s = '"' + OS.getenv("SQUISH_PREFIX") + '/bin/squishrunner"'
    if (squishserverHost != null) {
        s += ' --host=' + squishserverHost;
    }
    if (squishserverPort != null) {
        s += ' --port=' + squishserverPort;
    }
    s += ' --config addAUT "' + aut + '" "' + path + '"';
    if (OS.name == "Windows" && s.substr(-1) == '"') {
        s = '"' + s;
    }
    test.log("Executing: " + s);
    OS.system(s);
}
test.js

Related Information