We are building a new experience for our SmartBear Community.
This site is now read-only. You can still browse and search as usual. Learn More
This site is now read-only. You can still browse and search as usual. Learn More
Different script languages have a functionality like "Evaluate" or "eval" which will take any string and evaluate it as such. It works well but it does run some risks.
There is a method of Runner.CallMethod (https://support.smartbear.com/testcomplete/docs/reference/project-objects/items/script/runner/callmethod.html). It's listed as obselete because it had been the means, before, of calling methods from other script units. That's no longer necessary. But for doing the kind of data reflection you're wanting to do, this still works well.
If your method to be invoked is a method on an object, you can use aqObject.CallMethod instead (https://support.smartbear.com/testcomplete/docs/reference/program-objects/aqobject/callmethod.html).
I created a kind of data reflection myself as part of the mini-framework I have under development. The code is below. It requires a certain structuring for creating the classes themself (each class is a script unit named for the class with a method called "returnClass" which returns an instance of the object. I use the flexibility of the Runner.CallMethod means of doing this which works well in my situation:
/* Initial source retrieved from https://bitbucket.org/tristaanogre/tabledrivenframework and developed by Robert Martin.
The initial source is under a Creative Commons Creative Commons Attribution-ShareAlike 4.0 International License and any
modifications to this source are similarly available under the same license */
function toProperties(listProperties) {
var listLength,
listPropertyName,
listPropertyValue,
listPropertyString;
listLength = aqString.GetListLength(listProperties);
listPropertyString = '';
for (var i = 0; i<listLength; i += 2){
listPropertyName = aqString.GetListItem(listProperties, i);
listPropertyValue = aqString.GetListItem(listProperties, i+1);
listPropertyString = listPropertyString + '"' + listPropertyName + '": "' + listPropertyValue + '", ';
}
return JSON.parse('{' + aqString.SubString(listPropertyString, 0, aqString.GetLength(listPropertyString)-2) + '}');
}
function returnClass(className, properties){
var classMethod = className + ".returnClass";
var localObject = Runner.CallMethod(classMethod)
if (properties === undefined) {
properties = "";
}
localObject.data = toProperties(properties);
return localObject;
}Hiya,
Normally - there are better ways to avoid this entirely. I'd say re-evaluate your design and see if eval is really the only way to go
For example you can export your function and call it in another file.
EDIT: I noticed you had params. Edited my solution to include params too.
// file1
function foo(str) {
console.log('foo' + str)
}
function bar(str, str2) {
console.log('bar' + str + str2)
}
module.exports = { foo, bar }
// file2
const str = 'foo'
function runner(methodName, paramsArr) {
return require('file1')[methodName](...params) //use es6 spread operator to cater to any num of params
}
KSQian That is a neat trick. The framework that I posted the code from up thread has the Runner.CallMethod embedded in a script extension... which is JScript which is es3, not 6, so unfortunately I can't use that there... But it is something I'm going to tuck away in my bag of tricks for future reference.
Gotcha Robert!
es3 has apply which is another way of doing the same thing:
// file2
const str = 'foo'
function runner(methodName, paramsArr) {
return require('file1')[methodName].apply(this, paramsArr)
}
KSQian:
Nice trick, indeed...
With the only disadvantage that eval() or evaluate() exists in (almost?) any script language. This means that it will be much easier to port the code to VBScript/DelphiScript/Python if test code contains as little JScript-specific code as possible... :)