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() :

Python Example

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 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>")

    # Copying to clipboard may take a short moment:
    snooze(0.1)

    # Use getClipboardText() to get the text data
    # in the clipboard; also see:
    # https://doc.froglogic.com/squish/latest/rgs-squish.html#getClipboardText-function
    return getClipboardText()


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

JavaScript Example

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 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>");

    // Copying to clipboard may take a short moment:
    snooze(0.1);

    // Use getClipboardText() to get the text data
    // in the clipboard; also see:
    // https://doc.froglogic.com/squish/latest/rgs-squish.html#getClipboardText-function
    return getClipboardText();
}


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

Use in other Squish packages

It is still possible to automate Windows shells from within Squish for Qt for example. For this a running server from a Squish for Windows Package is required on the system.

In the startApplication call that starts the shell, you additionally need to pass the port for the Squish for Windows Server.

Also you will need a call to testSettings.setWrappersForApplication , to set the wrappers for the Windows shell toWindows, if you are running a test suite that is configured for a different wrapper.

testSettings.setWrappersForApplication("{}\\System32\\cmd.exe".format(os.getenv("WINDIR")),("Windows"))