This topic contains information about handling strings in C# and C++ scripts and provides examples of operations over strings. It contains the following sections:
Accessing individual character of a string
Searching for characters and substrings
Removing extra spaces from a string
Basics
A string is a sequence of symbols or digits. Strings are among the most frequently used data types. Like any other data types, strings in TestComplete are represented as OLE-compatible variants.
In C#Script and C++Script, a sequence of literal characters enclosed in a matching pair of quotation marks is recognized as a string. The quotation marks could be either single (') or double ("). The quotation characters are allowed within a string if they do not match the enclosing pair. All the following strings are valid:
C++Script, C#Script
str1 = "The brig was heading to Liverpool, when the captain noticed a ship.";
str2 = 'It came out of night fog and looked weird: no sails, no lights and no crew.';
str3 = "'Ahoy! Is there anyone?' - the captain cried.";
str4 = '"Nobody." - was the answer.'
To deal with strings, TestComplete has a special aqString
scripting object. The object is available for all supported scripting languages, so that you can use it to operate with string values regardless of the chosen language.
Method, Property | Description |
---|---|
aqString.AddListItem |
Adds a new item to a string list. |
aqString.ChangeListItem |
Changes the value of the string list item with the given index. |
aqString.Compare |
Compares two specified strings. |
aqString.Concat |
Concatenates two specified strings. |
aqString.DeleteListItem |
Removes an item with the given index from a string list. |
aqString.Find |
Searches for a substring within the given string. Use this method instead of the obsolete aqString.Contains . |
aqString.Format |
Generates a formatted string. |
aqString.GetChar |
Retrieves a single character from the input string. |
aqString.GetLength |
Returns the number of characters in a string. |
aqString.GetListItem |
Returns an individual item from the list passed through the input string. |
aqString.GetListLength |
Returns the number of items in the string list. |
aqString.Insert |
Inserts one string to another at the specified position. |
aqString.ListSeparator |
Specifies a character used to separate individual values in a list. |
aqString.Quote |
Encloses the specified string in quotes. |
aqString.QuoteSymbol |
Specifies a symbol used as a quotation mark. |
aqString.Remove |
Removes a number of characters from the input string. |
aqString.Replace |
Replaces all the occurrences of one substring with another substring. |
aqString.SubString |
Retrieves a substring from the input string. |
aqString.ToLower |
Converts the specified string to lower case. |
aqString.ToUpper |
Converts the specified string to upper case. |
aqString.Trim |
Removes spaces and control characters from the specified string. |
aqString.Unquote |
Converts a quoted string to an unquoted string. |
Another scripting object that is useful for string manipulation is aqConvert
. This object has several methods that convert values of different types to a string representation and vice versa.
Method | Description |
---|---|
aqConvert.CurrencyToFormatStr |
Converts a currency value to a string using the specified format settings. |
aqConvert.CurrencyToStr |
Converts a currency value to a string. |
aqConvert.DateTimeToFormatStr |
Converts the given date value to a string using the specified format. |
aqConvert.DateTimeToStr |
Converts the given date value to a string. |
aqConvert.FloatToStr |
Converts a floating-point value to a string. |
aqConvert.IntToStr |
Converts the given number into a string. |
aqConvert.StrToCurrency |
Converts the specified string to a currency value. |
aqConvert.StrToDate |
Converts the specified string to a date value. |
aqConvert.StrToDateTime |
Converts the specified string to a date/time value. |
aqConvert.StrToFloat |
Converts the specified string to a floating-point value. |
aqConvert.StrToInt |
Converts the specified string to an integer value. |
aqConvert.StrToInt64 |
Converts the specified string to a long integer value. |
aqConvert.StrToTime |
Converts the specified string to a time value. |
aqConvert.VarToStr |
Converts the specified variant value to a string. |
Furthermore, C#Script and C++Script languages have their own inherent object String
, that is, a wrapper for a string data type. The strings that are used in TestComplete are compatible with this object, moreover, the String
objects are created implicitly for every string. That is, you can call the object methods not only for object instances but for any TestComplete string. For example, the following method call is correct:
C++Script, C#Script
...
myStr = "This is my string";
mySubStr = myStr["substr"](11, 6);
...
A detailed description for the String
object is provided in the MSDN library, the table below lists its major properties and methods:
Property, Method | Description |
---|---|
length | Property. Returns the length of the string. |
charAt(index) | Method. Returns the character at the specified position. |
charCodeAt(index) | Method. Returns an integer representing the Unicode encoding of the character at the specified location. |
concat([string2[, string3[, . . . [, stringN]]]]) | Method. Returns a string value containing the concatenation of two or more supplied strings. |
fromCharCode([code1[, code2[, ...[, codeN]]]]) | Method. Returns a string that corresponds to the specified Unicode character numbers. |
indexOf(subString[, startIndex]) | Method. Returns the character position where the first occurrence of a substring occurs. |
localeCompare(stringExp) | Method. Returns a value indicating whether two strings are equivalent in the current locale. |
match(rgExp) | Method. Executes a search on a string using a regular expression pattern, and returns an array containing the results of that search. |
replace(rgExp, replaceText) | Method. Returns a copy of a string with text replaced using a regular expression or search string. |
search(rgExp) | Method. Returns the position of the first substring match in a regular expression search. |
slice(start, [end]) | Method. Returns a section of a string. |
split([separator[, limit]]) | Method. Returns the array of strings that results when a string is separated into substrings. |
substr(start [, length ]) | Method. Returns a substring beginning at a specified location and having a specified length. |
substring(start, end) | Method. Returns the substring at the specified location within a string. |
toLocaleLowerCase() | Method. Returns a string where all alphabetic characters have been converted to lowercase, taking into account the current locale. |
toLocaleUpperCase() | Method. Returns a string where all alphabetic characters have been converted to uppercase, taking into account the current locale. |
toLowerCase() | Method. Returns a string where all alphabetic characters have been converted to lowercase. |
toUpperCase() | Method. Returns a string where all alphabetic characters have been converted to uppercase. |
toString([radix]) | Method. Returns a string representation of an object. |
Special characters
There are several pairs of symbols that are used to represent special characters in C#Script / C++Script strings. They all start with a backslash character (\), and are often called escape characters. The following escape characters are allowed.
Character sequence | Description |
---|---|
\& | Ampersand |
\\ | Backslash |
\b | Backspace |
\r | Carriage return |
\" | Double quote |
\f | Form feed |
\n | New line |
\' | Single quote |
\t | Tab |
Getting the string length
To obtain the total number of characters in a string, you can either read the length
property of the native String
object., or call the aqString.GetLength
method. In JScript, the character position is zero-based, so the maximum position number in a string is Length-1. The following code demonstrates both ways of obtaining the string length:
C++Script, C#Script
function StringLengthDemo()
{
var aString;
aString="Some text";
Log["Message"]("The string is " + aString["length"] + " character(s) long.");
Log["Message"]("The string is " + aqString["GetLength"](aString) + " character(s) long.");
}
Using TestComplete, you can limit the length of string parameters returned by functions of the tested application. For this purpose, use the Maximum string length of [out] parameters project property. If the length of the string returned from the application via one of its out parameters exceeds the property’s value, TestComplete treats the returned string as a null one. |
Concatenating strings
The operation that makes up a string out of several others is called concatenation. The aqString
object and the native String
object of C#Script and C++Script have special methods (aqString.Concat
and String.concat
) that perform this operation.
However, it is much more convenient to use the addition operator (+) for this purpose. If one of the addition operands is a string, then the performed operation is considered to be string concatenation rather than number addition. In this case all other operands are converted to a string and the resulting string is formed.
The sample code below demonstrates how to use all three techniques:
C++Script, C#Script
function ConcatenationDemo()
{
var Str1 = "String No 1 ";
var Str2 = "String No 2 ";
var Str3 = "String No 3 ";
Log["Message"](Str1["concat"](Str2, Str3));
Log["Message"](aqString["Concat"](Str1, Str2));
Log["Message"](Str1 + "String No 2 " + "String No " + 3 + " ");
}
Comparing strings
Comparison of two strings is widely used during testing. Generally, a test procedure obtains textual data (user input, file contents, property values and so on) and then compares it with the expected data. The TestComplete aqString
and native String
objects have methods used to compare string values. These methods are: aqString.Compare
and String.localeCompare
.
The aqString.Compare
method has three parameters: two of them, String 1 and String2, specify the strings to be compared, while the last parameter defines whether the comparison should be case-sensitive or not.
The native String object of C#Script and C++Script has its own method, Str1.localeCompare(Str2)
, that compares the text of the current object instance (Str1) with another string specified by the Str2 parameter. The comparison is case-sensitive and it is made in accordance with the local settings. The method returns -1 if Str1 is less than Str2, 1 if Str1 is greater than Str2 and 0 if the strings are the same.
Both methods can compare strings holding specific national symbols, for example characters with diacritical marks ( , , and others).
The code below demonstrates how to use the above-mentioned methods:
C++Script, C#Script
// This helper function obtains an integer comparison result from the
// localeCompare routine and returns a textual interpretation of the result.
function GetComparisonStr(IntegerComparisonResult)
{
if (IntegerComparisonResult == 0)
return IntegerComparisonResult + '. The strings are the same.';
else
return IntegerComparisonResult + '. The strings are different.';
}
function StringComparison()
{
// Use the method of the native String object
Log["Message"]("\"Abra\"[\"localeCompare\"](\"abra\"): " + GetComparisonStr("Abra"["localeCompare"]("abra")));
Log["Message"]("\"abra\"[\"localeCompare\"](\"Abra\"): " + GetComparisonStr("abra"["localeCompare"]("Abra")));
Log["Message"]("\"abra\"[\"localeCompare\"](\"abra\"): " + GetComparisonStr("abra"["localeCompare"]("abra")));
// Use the method of the aqString object
Log["Message"]("aqString[\"Compare\"](\"Abra\", \"abra\", false): " + aqString["Compare"]("Abra", "abra", false));
Log["Message"]("aqString[\"Compare\"](\"Abra\", \"abra\", true): " + aqString["Compare"]("Abra", "abra", true));
// Work with native-language characters
// The following code assumes that the French layout is installed on the computer
// 040C - is the identifier of the French layout
if ( aqEnvironment["IsLanguageSupported"](0x040C) && aqEnvironment["SetKeyboardLayout"](Sys["Process"]("TestComplete")["Id"], "0000040c"))
{
Log["Message"]("\"français\"[\"localeCompare\"](\"Français\"): " + GetComparisonStr("français"["localeCompare"]("Français")));
Log["Message"]("\"français\"[\"localeCompare\"](\"français\"): " + GetComparisonStr("français"["localeCompare"]("français")));
Log["Message"]("\"français\"[\"localeCompare\"](\"francais\"): " + GetComparisonStr("français"["localeCompare"]("francais")));
Log["Message"]("aqString[\"Compare\"](\"français\", \"Français\", false): " + aqString["Compare"]("français", "Français", false));
Log["Message"]("aqString[\"Compare\"](\"français\", \"Francais\", false): " + aqString["Compare"]("français", "Francais", false));
Log["Message"]("aqString[\"Compare\"](\"français\", \"Français\", true): " + aqString["Compare"]("français", "Français", true));
}
}
Accessing individual character of a string
The C# and C++ scripting languages have no datatype intended for storing single symbols. However, this is not a problem, since the string type can hold a series of characters as well as individual characters. Moreover, you can extract a single character from a string using the aqString.GetChar
and String.charAt
methods. The sample routine below demonstrates how to use them. It posts the given text to the TestComplete log in two different ways: as a whole string and by a single letter.
C++Script, C#Script
function StringByLetter()
{
var aString="Per aspera ad astra";
Log["Message"]("The string is : " + aString);
Log["Message"]("And now this text letter by letter using aqString.GetChar:")
for (i = 0; i < aqString["GetLength"](aString); i++)
Log["Message"](aqString["GetChar"](aString, i));
Log["Message"]("And now this text letter by letter using String.charAt:")
for (i = 0; i < aString["length"]; i++)
Log["Message"](aString["charAt"](i));
}
Searching for characters and substrings
One of the most common tasks that one has to perform when working with string values is determining whether specific text is part of a string. To perform such tasks, the aqString
object has the Find
method. If the specified substring was found, the method returns the number of the first occurrence of the substring within the source string. If the specified substring was not found, the method returns -1:
C++Script, C#Script
function StringOccurrenceDemo()
{
var aString = "Per aspera ad astra";
var aSubString = "astra";
var Res;
Res = aqString["Find"](aString, aSubString)
if (Res != -1)
Log["Message"]("A substring '" + aSubString + "' was found in string '" + aString+"'" + " at position " + aqConvert.IntToStr(Res));
else
Log["Message"]("There are no occurrences of '" + aSubString + "' in '" + aString + "'.");
}
You can also get the position where the specified substring occurs using the native method indexOf
of the String
object. If the substring was found, the method returns the initial position (from 0) of the first substring match. If no occurrences were found, the method returns -1. The code below demonstrates how to use it:
C++Script, C#Script
function TextPosDemo()
{
var aString = "Per aspera ad astra";
var aSubString = "astra";
var findpos;
findpos = aString["indexOf"](aSubString);
if (findpos != -1)
Log["Message"]("A substring '" + aSubString + "' was found at position " + findpos);
else
Log["Message"]("There are no occurrences of '" + aSubString + "' in '" + aString + "'.");
}
Getting a substring
The aqString
object and the native String
object of C#Script and C++Script have several methods that allow you to extract a substring from a string. They are SubString
, substring, substr
and slice
. These methods vary in how the extracted substring is defined.
The String.substring
method returns a text fragment that lies between starting and ending character positions. The character at the ending position is not included. The position is zero-based. If starting position is greater than ending position, then these values are swapped. The negative values are considered as zeros.
The String.slice
method is similar to substring
, yet, it has its own specific characters. In this method the substring is also specified by the starting and ending positions. However the ending position can be omitted, in this case the substring lasts until the end of the initial string. If the starting position is greater than the ending position, then the empty string is returned. The negative values are allowed and are interpreted as position calculated as a given absolute value subtracted from the string length.
The SubString
method returns a text fragment of the input string that starts at the given position and has the specified length. The String.substr
method works in a similar way, however it does not require that the input string be passed as the parameter, since every String
object instance already refers to a string. Thus, the String.substr
method has only two parameters: the first one specifies the starting position, while the second defines the length of the retrieved fragment. The length parameter is optional, and if it is omitted, then the resulting substring continues up to the end of the source string. If the length parameter is negative or zero, then an empty string is returned. Undefined, negative and zero values of the position parameter are interpreted as the first character in a string.
The sample code below demonstrates how to use all these methods:
C++Script, C#Script
function GetStringDemo()
{
var Str = "0123456789";
Log["Message"]("The 'String.substring' method demo:")
Log["Message"](Str["substring"](2, 7)); // Posts "23456"
Log["Message"](Str["substring"](7, 2)); // Posts "23456"
Log["Message"](Str["substring"](-2, 7)); // Posts "0123456"
Log["Message"](Str["substring"](2, 2)); // Posts ""
Log["Message"]("The 'String.slice' method demo:")
Log["Message"](Str["slice"](2, 7)); // Posts "23456"
Log["Message"](Str["slice"](2)); // Posts "23456789"
Log["Message"](Str["slice"](-8, -3)); // Posts "23456"
Log["Message"](Str["slice"](7, 2)); // Posts ""
Log["Message"]("The 'aqString.SubString' method demo:")
Log["Message"](aqString["SubString"](Str, 2, 5)); // Posts "23456"
Log["Message"](aqString["SubString"](Str, 2, 0)); // Posts ""
Log["Message"]("The 'String.substr' method demo:")
Log["Message"](Str["substr"](2, 5)); // Posts "23456"
Log["Message"](Str["substr"](2)); // Posts "23456789"
Log["Message"](Str["substr"](-2, 3)); // Posts "012"
Log["Message"](Str["substr"](2, 0)); // Posts ""
}
Splitting strings
Sometimes it is required to make several strings out of a single string. This operation splits a string into substrings. It can be performed by the native split
method of C#Script and C++Script. This method searches the string for delimiter character(s) (defined either as string or as a regular expression), separates the string and returns an array holding the constituent strings. Also you can constrain the maximal array length with the third parameter. It is not obligatory and can be omitted. The same method can be used to split a string onto substrings, sentences and even separate words, it all depends on the specified delimiter. The first sample routine below uses a space character as a delimiter to extract words out of a string and the second routine splits the string by line breaks:
C++Script, C#Script
function SplitDemo()
{
var s, ss;
s = "Better late than never but better never late.";
// Split at each space character.
ss = s["split"](" ");
Log["Message"]("The resulting array is: " + ss);
Log["Message"]("There are " + ss["length"] + " words in the array");
Log["Message"]("The first word is: " + ss[0]);
}
function SplitDemo2()
{
var s, ss;
s = "Better late than never\r\nbut better never late.";
// Split at line break character.
ss = s["split"]("\r\n");
Log["Message"]("The resulting array is: " + ss);
Log["Message"]("There are " + ss["length"] + " words in the array");
Log["Message"]("The first word is: " + ss[0]);
}
TestComplete has a similar method called aqString.GetListItem. It extracts a substring with the specified index from the input string. It was designed to read items from string lists, see Working with string lists for more information. However, it allows you to redefine the delimiter characters and, like the split
method, it can be used to get sentences, single words and so on.
C++Script, C#Script
function SplitDemo3()
{
var s, ss , prevSep;
s = "Better late than never but better never late.";
// Assign list separator to space character
prevSep=aqString["ListSeparator"];
aqString["ListSeparator"] = " ";
Log["Message"]("There are " + aqString["GetListLength"](s) + " words in a string");
Log["Message"]("The first word is: " + aqString["GetListItem"](s, 0));
// Restore previous separator
aqString["ListSeparator"] = prevSep;
}
Removing extra spaces from a string
The aqString
object has a special routine, aqString.Trim
, that excludes leading and trailing spaces from a string. Generally, this method is used to remove unnecessary spaces at the beginning and at the end of strings obtained from the user input.
C++Script, C#Script
function TrimDemo()
{
var str=" Hallo ";
Log["Message"]("'" + aqString["Trim"](str, aqString["stLeading"]) + "'"); // Posts 'Hallo '
Log["Message"]("'" + aqString["Trim"](str, aqString["stTrailing"]) + "'"); // Posts ' Hallo'
Log["Message"]("'" + aqString["Trim"](str, aqString["stAll"]) + "'"); // Posts 'Hallo'
}
Another function that can be useful when handling user input strings is excluding extra inner spaces out of the string. This function seems to be similar to Trim
, but the latter only removes spaces at the beginning or end of the string and does not affect the spaces inside the string. The general idea of the function is for the string to be parsed into separate words and then a new string is constructed. The new string consists of the same words but is separated with a single space between words.
C++Script, C#Script
function TrimInner(Str)
{
var WordArray;
WordArray = Str["split"](/ +/);
Str = "";
for (i = 0; i < WordArray["length"]; i++) Str = Str + WordArray[i] + " ";
return Trim(Str);
}
// An example of how to use this function
function TrimInnerDemo()
{
Log["Message"](TrimInner("Follow the white rabbit"));
}
Replacing characters and substrings
Quite often, one needs to find and replace a character or a substring within a string. There are two ways to do this: by using the aqString.Replace
method or by using the replace
method of the String
object.
The aqString
object method is much easier to use. It can be used when you need to change a certain character or string. It allows you to specify whether the search should be case-sensitive or not. Here is an example of how to use this method:
C++Script, C#Script
function StringReplaceDemo()
{
var str = "Hi, Bob. Have you seen Bob Robbinson?";
str = aqString["Replace"](str, "Bob", "Jack", true);
Log["Message"](str);
}
The String
object method is a little more complicated, but it offers more flexibility. You can change not only a definite character or string, but all fragments matching the specified regular expression pattern. The regular expression pattern is defined between two slash ("/") characters, additionally you can set the following flags that can be combined: g - perform global search for all occurrences of pattern, i - ignore case and m - perform a multiline search. For a full description of how to use regular expressions refer to the Introduction to Regular Expressions article in the MSDN library.
The first sample demonstrates how to change a definite string using the replace
method.
C++Script, C#Script
function RegExReplaceDemo1()
{
var str = "Hi, Bob. Have you seen Bob Robbinson?";
var re;
// Define regular expression pattern.
re = /Bob/g;
// Perform replace operation
str = str["replace"](re, "Jack");
Log["Message"](str);
}
The second example shows how to replace a substring with alternative parts. The patterns of alternative parts are separated by pipe characters (" | "). For instance, in the sample below, the /ht(ml|m)/ pattern matches both html and htm:
C++Script, C#Script
function RegExReplaceDemo2()
{
var str = "The html is widely used in Internet. The HTM file is a text file with tags.";
var re;
// Define regular expression pattern.
re = /ht(ml|m)/gi;
// Perform replace operation
str = str["replace"](re, "hypertext markup language");
Log["Message"](str);
}
Furthermore, using regular expressions you can search for the text fragments matching the specified format. In the next sample, all dates written in the DD/MM/YYYY format are substituted with the Some Date string. This operation can be useful, for example, when comparing two reports that contain the generation date.
C++Script, C#Script
function RegExReplaceDemo3()
{
var str = "Date of report: 30/04/2005.";
var re;
// Define regular expression pattern.
re = /\d{1,2}.\d{1,2}.\d{2,4}/g;
// Perform replace operation
str = str["replace"](re, "Some Date");
Log["Message"](str);
}
Changing the letter case
A string can contain uppercase and lowercase letters. The TestComplete aqString
object and the native String
object have methods that convert uppercase letters to lowercase ones and vice versa. They are: aqString.ToLower, aqString.ToUpper, String.toLowerCase
and String.toUpperCase
.
The code below demonstrates how all of these methods are applied.
C++Script, C#Script
function LetterCaseDemo()
{
var str="The word 'Champagne' is of French origin"
// Converting to lower case
Log["Message"](aqString["ToLower"](str));
Log["Message"](str["toLowerCase"]());
// Converting to upper case
Log["Message"](aqString["ToUpper"](str));
Log["Message"](str["toUpperCase"]());
}
Working with string lists
Some scripting objects, generally these are controls like ListBoxes, ComboBoxes and Memos, return data about their state or contents as string lists. The individual data elements (or items) in this list are separated by commas, line breaks, carriage returns or some other delimiter characters.
The aqString
object has a number of specific methods (AddListItem
, ChangeListItem
, DeleteListItem
, GetListItem
and GetListLength
) that are intended to deal with such lists of textual data. The AddListItem
and DeleteListItem
methods add a new item to the list or remove an existing item respectively. The GetListItem
method retrieves the item with the given index, and ChangeListItem
assigns a new value to the given item. The GetListLength
method returns the total number of items in the string list.
The symbol that is used as a separator of list items is defined by the ListSeparator
property. By default, the list separator is a pipe ( | ), but it can also be a comma, column, line break, carriage return, tabulation, and any other printable and non-printable character, or even several characters.
Here is a sample that demonstrates how to work with string lists returned by scripting objects.
C++Script, C#Script
function ListDialogOptions()
{
var OptStr, prevSep;
// Get a string with dialog options
OptStr = UserForms["UserForm1"]["SaveDialog1"]["Options"];
// Set a comma as the list separator
prevSep = aqString["ListSeparator"];
aqString["ListSeparator"] = ",";
// Get the number of dialog options
Log["Message"]("The dialog has " + aqString["GetListLength"](OptStr) + " option(s) enabled:");
// Iterate through the options list
for (i = 0; i < aqString["GetListLength"](OptStr); i++)
// Get the option and post it to the log
Log["Message"]("Option No " + (i+1) + " is: " + aqString["GetListItem"](OptStr, i));
// Restore the previous separator
aqString["ListSeparator"] = prevSep;
}
function ManageMemoText()
{
var StrList,prevSep;
// Get a string with memo lines
StrList = UserForms["UserForm1"]["cxMemo1"]["Lines"]["Text"];
// Post the memo contents to the log
Log["Message"](UserForms["UserForm1"]["cxMemo1"]["Lines"]["Text"]);
// Set a newline character as the list separator
prevSep = aqString["ListSeparator"];
aqString["ListSeparator"] = "\n";
// Append one more line
StrList = aqString["AddListItem"](StrList, "Last Line");
Log["Message"](StrList);
// Change the value of the first line
StrList = aqString["ChangeListItem"](StrList, "New First Line", 0);
// Change the memo contents
UserForms["UserForm1"]["cxMemo1"]["Lines"]["Text"] = StrList;
// Post the memo contents to the log
Log["Message"](UserForms["UserForm1"]["cxMemo1"]["Lines"]["Text"]);
// Restore the previous separator
aqString["ListSeparator"] = prevSep;
}