Javascript for TestComplete
Dear community I just released a course for teaching Javascript to TestComplete testers interested in learning how Javascript works so that they can take advantage of this powerful scripting language inside of TestComplete. The course is purely Javascript to explain all the ins and outs. Everything you learn in the course is 100% usable in TestComplete. The course is free! https://github.com/TheTrainingBoss/Javascript-for-TestComplete Enjoy and good luck! -Lino3.8KViews10likes4CommentsLaunch Browser in Incognito/Private Mode
Thought of sharing the code in the community for launching browsers in their incognito modes. The function is parameterized such a way to run for the browsers Internet Explorer, Edge, Chrome and Firefox. Hope it will be useful for more people. function runIncognitoMode(browserName){ //var browserName = "firefox" //iexplore,edge,chrome,firefox if (Sys.WaitBrowser(browserName).Exists){ var browser = Sys.Browser(browserName); Log.Enabled = false // To disable the warning that might occur during closing of the browser browser.Close(); Log.Enabled = true // enabling the logs back } if(browserName=="edge"){ Browsers.Item(btEdge).RunOptions = "-inprivate" Delay(3000) Browsers.Item(btEdge).Run(); }else if (browserName=="iexplore"){ Browsers.Item(btIExplorer).RunOptions = "-private" Delay(3000) Browsers.Item(btIExplorer).Run(); }else if (browserName=="chrome"){ Browsers.Item(btChrome).RunOptions = "-incognito" Delay(3000) Browsers.Item(btChrome).Run(); }else if (browserName=="firefox"){ Browsers.Item(btFirefox).RunOptions = "-private" Delay(3000) Browsers.Item(btFirefox).Run(); } Sys.Browser(browserName).BrowserWindow(0).Maximize() }3.5KViews7likes3CommentsAdvanced search object for complex model
Hello all, Please find here my implementation of advanced search of in-memory object for complex tree model. Sometimes when the tested app is really complex (especially in heavy client application), the search for object could be too slow due to depth. One of the solution is to do by finding intermediate object to narrow and guide the search. So you multiply findChildEx. To ease that i made the followg method : /** * <a id="system.findContainer"></a> * Rechercher un objet TestComplete en mémoire de manière containérisé<br> * Si <i>system.debug</i> est à <b>true</b> alors des logs complémentaires sur la recherche sont inscrits * @memberof system * @function * {Object} ParentObject - Objet parent porteur de l'objet à rechercher. Racine de départ de la recherche. Plus l'objet parent est de haut niveau, plus le temps de recherche peut être long * {array} Props - Tableau des propriétés des objets à rechercher par container, si plusieurs propriétés recherchées pour un container donnée alors le séparateur est le |, exemple ["Visible|Name", "Name"] -> recherche des 2 propriétés Visble et Name pour le premier container et recherche de Name seulement pour le deuxième container * {array} Values - Tableau des valeurs des propriétés des objets à rechercher * {number|array} [Depth=4] - Limiter la recherche a <i>Depth>/i> profondeur depuis l'objet parent. Plus la profondeur est grande, plus le temps de recherche peut être long. Peut être un tableau pour définir un temps de rechercher par container * @returns {object} Renvoie l'objet s'il existe ou <b>null</b> le cas échéant ou bien en cas d'erreur */ system.findContainer = function(ParentObject = null, Props = null, Values = null, Depth = 4) { // Vérification des paramètres obligatoires if ((ParentObject == null) || (Props == null) || (Values == null)) { if (system.debug) Log.Message('findContainer() - Un paramètre obligatoire est non renseigné (ParentObject ou Props ou Values)', "", pmHigher, system.logWarning); return null; } if (ParentObject == "current") { if ((typeof system.container != 'undefined') && (system.container != null) && (system.container.Exists)) ParentObject = system.container else return null; } if (system.debug) { let propsKey = typeof Props == "string" ? Props : Props.join("|"); let valuesKey; switch (typeof Values) { case "string": valuesKey = Values; break; case "number": case "boolean": valuesKey = Values.toString(); break; case "null": valuesKey = "null"; break; default: valuesKey = Values.join("|"); break; } Log.Message("findContainer(" + ParentObject.FullName + ", " + propsKey + ", " + valuesKey + ", " + Depth.toString() + ") - Recherche d'objet", "", pmLowest, system.logDebug); } var objectfind = ParentObject; let currentProps; let currentValues; let currentDepth; try { for (let i=0;i<Props.length;i++) { currentProps = Props[i].split('|'); currentValues = new Array(); currentDepth = typeof Depth == 'number' ? Depth : Depth[i]; for (let j=0;j<currentProps.length;j++) { currentValues.push(Values.shift()); } objectfind = objectfind.FindChildEx(currentProps, currentValues, currentDepth, true, system.time.medium); if ((typeof objectfind == 'undefined') || ((objectfind != null) && (!objectfind.Exists))) break; } } catch (e) { objectfind = null; if (system.debug) Log.Message("findContainer() - Une exception est apparue dans la recherche", e.message, pmHighest, system.logError); } finally { // Ne renvoyer que "null" sur non trouvé ou erreur if ((typeof objectfind == 'undefined') || ((objectfind != null) && (!objectfind.Exists))) objectfind = null; if (system.debug) { if (objectfind == null) Log.Message("findContainer() renvoie un objet null ou undefined", "", pmLowest, system.logDebug) else Log.Message('findContainer() a trouvé un objet', objectfind.FullName, pmLowest, system.logDebug); } return objectfind; } } It comes from my testing framework so everything starting by system. is specific but you should understand the use : system.debug -> true to activate an additionnal level of log. system.logDebug -> specific debug log attributes. system.container -> a global variable that can hold a frequently used object in portion of test system.time.medium -> this is 5 seconds (5000ms) Samples usage : let objectToTest = system.findContainer(SourceObject, ["Visible|Name", "Visible|Name"], [true,'dlmAccueil', true,'editionEnfants']); Will search in SourceObject a visible object named 'editionEnfants' which is located inside another visible object named 'dlmAccueil'. The search will use a default max depth of 4 levels for both objects. let objectToTest = system.findContainer(SourceObject, ["Visible|Name", "Name", "Header|Index|Visible"], [true, "Saisie", "DockingPanel"', "ILPaneGroup", 1, true], [2, 3, 2]); Will search in SourceObject a visible object with property Index to 1 and property Header to 'ILPanelGroup' which is located inside another object named 'DockingPanel' which is located inside another visible object named 'Saisie'. The search will use a depth of 2 levels for first object, 3 levels for second object and 2 levels for final object. Hope it could help someone and feel free to discuss/improve it.1.4KViews3likes2Comments[TechCorner Challenge #1] Passing custom command-line arguments as test parameter
Hi Community! This resource we are creating together has gained so much value over the years. Tons of helpful content can be found in the TestComplete Community thanks to all of you! I propose that we take it to the next level by adding even more useful things to the TechCorner tag - a tag where we keep your tech articles, script examples, use cases, etc. Here's your chance to share expertise and contribute. Task:Write a script that will take the value of a custom argument from the TC command line and use this value to run a parameterized test. Difficulty: For example, imagine that you have a web test that takes the name of the browser as a parameter. The script should check the command line TC was launched with, find the /BrowserName parameter, read its value, and pass it to the web test as a parameter. If the command line contains /BrowserName=chrome, the web test should launch Chrome; for /BrowserName=firefox the web test should launch Firefox, etc. Good luck!Solved5.3KViews3likes7Comments[TechCorner Challenge #8] Finding Elements on a Web Page
Hi TestComplete Community! Today, I bring you a new TechCorner Challenge task 🙂 By completing the tasks, you will not only learn TestComplete features but also get into the TechCorner Leaderboard. Today we will use the Leaderboard table itself to sharpen your skills! Let’s use TestComplete to find out if a user is on the table and how many points they gained so far! Task: Create a TestComplete script that will go to theLeaderboard page, search for yourself (by your user name) and a user named tristaanogre in the table and, if this user is mentioned on the Leaderboard, post their score to the log. Can you compete with people in the Leaderboard?😊 Difficulty: Tip: You can useFindChildorFindElementin your script. Note: You will need a Web Module to fulfill this task. Good luck!Solved13KViews2likes7CommentsShare your writing guidelines on scripting - Focus on method writing
Hello all, Please share and discuss about your writing guidelines focused here on your standard way of building a script method. Below i give you mine, French inside. This is a standard guideline, not a strict rule, we adapt especially on the result type (not necessary a single boolean but can be a complex return). Template méthode d’un objet métier : Règle 101 – En-tête En-tête documentation de la méthode, respecter la syntaxe suivante permettant une génération automatisée de la documentation. /** * Description * @memberof nomObjetMetier * @function * @param {type paramètre} nom paramètre - description * @param {type paramètre} nom paramètre = valeur par défaut- description * @param {type paramètre} [nom paramètre optionnel = valeur par défaut] - description * @returns {type retour} description */ Type paramètre/type retour : string, number, boolean, Object Description : Les balises html peuvent être utilisées pour décorer la documentation générée. Les retours à la ligne doivent être traitée via l’inclusion balise <br> Exemple d’en-tête : /** * Appeler un écran Manhattan<br> * S'il est déjà ouvert alors bascule dessus<br> * Si l'écran est présent (après appel ou bascule) alors currentForm[ScreenCode] est associé à l'écran demandé * @memberof mhnEngine * @function * @param {string} ScreenCode - Code de l'écran à appeler ("Stock article", "Ordres de dis...", "oLPN", "Sites") * @param {boolean} [Shortcut = false] - <b>True</b> alors passe par click sur raccourci plutôt que par menu * @returns {boolean} Renvoie <b>true</b> si la fonction s'est exécutée sans erreur<br> * Si la fonction a échoué alors la propriété <i>errorString</i> est mise à jour avec la valeur de l'erreur sinon elle est mise à <b>""</b> */ Règle 102 – Nommage méthode Nom de la méthode : Nommage selon la règle Verbe d’action + Objet concerné, en lower camel-case. Exemple verbe d’action : call launch close delete get set create … Exemple d’objet concerné : Screen Menu Invoice Budget Lines … Exemple de nom de méthode : callScreen Règle 103 – Paramètres méthode Paramètres de la méthode : Nom court explicite en upper camel-case. Si possible, affecter une valeur par défaut au paramètre. Exemple de paramètres de méthode : (ScreenCode = "101CREATEREPORT", ByShortCut = false) Règle 104 – Corps méthode Corps de la méthode : Etapes à respecter : 1 – définir les valeurs par défaut des paramètres 2 – tracer la méthode appelée 3 – encadrer dans un try .. catch .. finally 4 – 1ere instruction du try .. est le contrôle de validité des paramètres obligatoires 5 – les variables internes de la méthode doivent être déclarées en lower camel-case (pour différencier des paramètres de la méthode qui sont en upper camel-case) 6 – le catch doit contenir un appel à la gestion générique des erreurs 7 – le finally garanti le suivi de retour 8 – Dans la mesure du possible ne faire qu’un retour de type boolean. Exemple : function callM3Screen (ScreenCode = "SC100", ByShortcut = false) 1 { if (system.debug) Log.Message("callScreen(" + ScreenCode + ", " + ByShortcut + ") - Appel d'un menu via l'en-tête ou les raccourcis", "", pmLowest); 2 try { 3 if ((ScreenCode == undefined) || (ScreenCode == "")) 4 throw Error("Le paramètre obligatoire ScreenCode est non renseigné !"); // Petite adaptation pour les ordres de distribution let screenCode2 5 = ScreenCode == "Ordres de dis..." ? "Ordres de distribution" : ScreenCode; … … … } catch(e) { errorString = e.message; 6 } finally { return (errorString == ""); 7 8 } } And an example of a standard system tools method with these guidelines, a usefule function to stop a process : /** * Arrêter/tuer un processus en mémoire * @memberOf system * @function * @param {string} ProcessName - Nom du processus a arrêter * @param {boolean} [SoftKill=false] - <b>true</b> alors essaye d'arrêter le processus de manière normale avec un <i>close/<i> avant de tenter un <i>terminate</i> dessus * @param {number} [Trials=10] - Nombre de tentative d'arrêt du processus avant de lever une erreur * @returns {boolean} Renvoie <b>true</b> si le processus a été arrêté, <b>false</b> si échec de l'arrêt ou une erreur s'est produite (journalisation) */ function killProcess(ProcessName = "", SoftKill = false, Trials = 10) { let result = true; if (system.debug) Log.Message("killProcess(" + ProcessName + ", " + SoftKill + ", " + Trials.toString() + ") - Arrêt de process", "", pmLowest, system.logDebug); try { if (ProcessName == "") throw Error("Le nom du processus n'est pas fourni !"); let i = 0; let p = Sys.FindChild("ProcessName", ProcessName); while (p.Exists) { i++; if (system.debug) Log.Message("Tentative d'arrêt n°" + i + " du process " + ProcessName + ", PID = " + p.Id, "", pmLowest, system.logDebug); if (SoftKill) { p.Close(); if (!p.WaitProperty("Exists", false)) p.Terminate(); } else p.Terminate(); if (i > Trials) throw Error("Le processus est toujours présent après " + Trials + " tentatives d'arrêt !"); p = Sys.FindChild("ProcessName", ProcessName); } } catch(e) { result = false; Log.Message("killProcess(" + ProcessName + ", " + SoftKill + ", " + Trials.toString() + ") - Echec arrêt process : " + e.message, "", pmHighest, system.logError); } finally { return result; } };1.3KViews2likes2CommentsOdd/Incorrect DDT Code Example in Documentation
Hi, I have been learning how to script 'Data Driven Tests' in TestComplete. The Documentation here : https://support.smartbear.com/testcomplete/docs/testing-with/data-driven/drivers.html Has some javascript examples which I tried out. But it did not seem to work too well. (You had to choose the Driver function each time) ie varRecNo; // Posts data to the log (helper routine) functionProcessData() { varFldr, i; Fldr = Log.CreateFolder("Record: " + aqConvert.VarToStr(RecNo)); Log.PushLogFolder(Fldr); for(i = 0; i < DDT.CurrentDriver.ColumnCount; i++) Log.Message(DDT.CurrentDriver.ColumnName(i) + ": " + aqConvert.VarToStr(DDT.CurrentDriver.Value(i))); Log.PopLogFolder(); RecNo = RecNo + 1; } // Creates the driver (main routine) functionTestDriver() { varDriver; // Creates the driver // If you connect to an Excel 2007 sheet, use the following method call: // Driver = DDT.ExcelDriver("C:\\MyFile.xlsx", "Sheet1", true); Driver = DDT.ExcelDriver("C:\\MyFile.xls", "Sheet1"); // Iterates through records RecNo = 0; while(! Driver.EOF() ) { ProcessData();// Processes data Driver.Next();// Goes to the next record } // Closes the driver DDT.CloseDriver(Driver.Name); } After examining the code I found it was not quite correct (Its like someone messed with it just to try to get it to run) I have corrected the code in the example to get it to working as I think it was intended. // Posts data to the log (helper routine) function ProcessData(RecNo) { var Fldr, i; Fldr = Log.CreateFolder("Record: " + aqConvert.VarToStr(RecNo)); Log.PushLogFolder(Fldr); for(i = 0; i < DDT.CurrentDriver.ColumnCount; i++) { Log.Message(DDT.CurrentDriver.ColumnName(i) + ": " + aqConvert.VarToStr(DDT.CurrentDriver.Value(i))); } Log.PopLogFolder(); } // Creates the driver (main routine) function TestDriver() { var Driver, RecNo; // Creates the driver // If you connect to an Excel 2007 sheet, use the following method call: // Driver = DDT.ExcelDriver("C:\\MyFile.xlsx", "Sheet1", true); Driver = DDT.ExcelDriver("C:\\MyFile.xls", "Sheet1"); // Iterates through records RecNo = 0; while (! Driver.EOF() ) { ProcessData(RecNo); // Processes data Driver.Next(); // Goes to the next record RecNo = RecNo + 1; } // Closes the driver DDT.CloseDriver(Driver.Name); } I hope it's of use to others 🙂 as it had me baffled for a while. (NB. Don't forget to press on the '>' symbol, next to each record output in the log, to see the data extracted from your spreadsheet.)Solved972Views1like2Comments[TechCorner Challenge #9] Generate a random number within a range
Hi Community! Another awesome task is ready🙂 By completing the task, you will not only learn TestComplete features but also get into the TechCorner Leaderboard. Participate in the challenge and earn new unique badges! Check out some of these awesome rewards: Let's imagine that you are testing an application that has gaming elements - a knight is using a legendary sword to slay a dragon! And, the sword will deliver damage in the following range - from 30 to 75. Instead of using the same number every time, you want to generate a random number on each run and enter it in the application. How would you do it in TestComplete? Let's see if we can get an example for each scripting language (JavaScript, JScript, Python, VBScript)! Task: Generate a random number within the following range (30-75) in TestComplete using a scripting language of your choice. Difficulty: Bonus: You will get an additional point for each script written in a different language. Best of luck!Solved11KViews1like10CommentsJavaScript Custom function for finding objects within the iframe
Hi Team, i am trying to find element objects within an ifram object, but im not able to do a object spy on those, so i had tried launching the browser by disabling the web securites and noticed that the time taken to find objects after i disable web securites is too long, hence trying towrite a javascript code which will be working similar to javascript executor in selenium, as so this will be used to find elements using xpath for even objects within the iframe object. please help me how to implement the same in testcomplete, waiting for valuable replies, thanks in advance. Thanks and Regards, Sathish Kumar KSolved1.4KViews1like3Comments[TechCorner Challenge #3] - Changing the options from outside of TestComplete
Hi TestComplete Community! I bring you another task for our weekly scripting challenge🙂 Learn new things about working with the product, and get into the TechCorner Leaderboard! Imagine that you need to change the TestComplete options on several machines - for example, set the JVM location. You don’t want to do it manually and decide to create a script and run it on each machine. How could this script look? We suggest using JScript or VBScript, but you choose PowerShell, Python, etc. Task: Create a script that changes TestComplete options from outside of TestComplete Difficulty: It is a bit more difficult than the tasks we posted here before, let's see how quickly you can solve his one!🙂 Upd: More hints! Follow these steps to solve this: 1. You need to modify the XML file that contains the TestComplete settings - tcSettings.xml. The file is located in %LOCALAPPDATA%/SmartBear/TestComplete/14.0. You can use the ExpandEnvironmentStrings method of the WScript.Shell object to obtain the %LOCALAPPDATA% environment variable value. 2. Open the XML fileand locate the node that should contain the option value. You can use the selectNodes or selectSingleNode methods of the DOMDocument object to get the needed node. 3. Set the needed value for the node attribute. 4. Save the XML file.Solved3.9KViews1like12Comments