JohanHOccasional ContributorJoined 10 years ago19 Posts9 LikesLikes received3 SolutionsView All Badges
ContributionsMost RecentMost LikesSolutionsRe: [Jenkins integration]: Test runner exit code: -6 Aha, well it seems like the TestCompleteService had stopped. It seems to that quite often which gives us a headache, since we have like 20 jenkins-slaves and manually logging into and checking them all the time is not a sustainable solution. I'll see if we can configure the service to restart on failure (if it is not already set up to do that). Thanks! [Jenkins integration]: Test runner exit code: -6 Hi, We have an automated test setup where we are running TestComplete tests via Jenkins. We are running Jenkins as a service and it has been working (sort of) rather good. Lately however I have noticed that suddenly a Jenkins node stops working and fails to run the test with exit code -6 (which I can find no reference to in the docs). After some time (and me trying to understand what it means, since the service clearly is there) it starts working again. Any idéas? Here is a full printout of the log: [TestComplete] The test execution started (TestCompleteSuite/Reliability/UserCreateUserAndLogon/RunTest). [TestComplete] Found TestComplete/TestExecute installations: Type: TE, Version: 12.10.590.11, Path: "C:\Program Files (x86)\SmartBear\TestExecute 12\bin\TestExecute.exe" [TestComplete] Selected TestComplete/TestExecute installation: Type: TE, Version: 12.10.590.11, Path: "C:\Program Files (x86)\SmartBear\TestExecute 12\bin\TestExecute.exe" [TestComplete] Launching the test runner. $ '"C:\Program Files (x86)\SmartBear\TestExecute 12\bin\TestCompleteService12.exe"' //LogonAndExecute //lDomain: "" //lName: "admin" //lPassword: ******** //lTimeout: "-1" //lUseActiveSession: "true" //lCommandLine: '""C:\Program Files (x86)\SmartBear\TestExecute 12\bin\TestExecute.exe" d:\dev\skynet\TestCompleteSuite\TestCompleteSuite.pjs /run /SilentMode /ForceConversion /ns /exit /ExportLog:d:\dev\skynet\2598651.tclogx /ExportLog:d:\dev\skynet\2598651.htmlx /ErrorLog:d:\dev\skynet\2598651.txt /ExportLog:d:\dev\skynet\2598651.mht /project:Reliability /unit:UserCreateUserAndLogon /routine:RunTest /DoNotShowLog"' [TestComplete] Test runner exit code: -6 (TestComplete Service is not available on the node). [TestComplete] [WARNING] Unable to find the log file "2598651.tclogx". [TestComplete] [WARNING] Unable to find the log file "2598651.htmlx". [TestComplete] [WARNING] Unable to find the log file "2598651.mht". [TestComplete] [WARNING] Errors occurred during the test execution. [TestComplete] Marking the build as FAILED. [TestComplete] [WARNING] Unable to publish test results (xml data is empty). [TestComplete] The test execution finished /Johan Re: Jenkins Environment Variables not available in Tests After much hard work I figured out what the problem is. We have installed Jenkins on the Slaves using Java Web Start as a service as described in the help section. The service is running as the System user. The TestComplete jenkins plugin is running on a different account (with admin rights). This means that any environment variables set up by Jenkins is set in the System user environment and is not accessible to the other users and processes running under those accounts, in this case the TestComplete process... I did try to run as the same user (i.e changing the user of the Jenkins slave service) and it worked for the environment variables but then I lost the possibility to interact with the desktop... very bad for GUI based application testing. So in the end we came up with this solution: In Jenkins add a 'Execute Windows batch command' build before the 'TestComplete Test' and write: set > %SystemRoot%\Temp\environment-variables-from-jenkins.txt Since we cannot access the environment variables we are forced to use a location we think exists in and is accessible by both accounts. In our Test we have written the following code that reads the file and sets the variables if the do not exist. # ------------------------------------------------- # Read eventual environment variables file to # enable Jenkins (or other) to transfer settings # by means of environment variables # ------------------------------------------------- env_file = os.path.join(os.getenv('SystemRoot'), 'Temp', 'environment-variables-from-jenkins.txt') if os.path.exists(env_file): with open(env_file) as f: lines = f.readlines() if lines: for name, value in [line.split('=', 1) for line in lines if line]: if not os.getenv(name): os.putenv(name, value.strip()) os.unlink(env_file) Do not forget to remove the file after read! Otherwise environment variables from one test may taint another. Hope this may help others that run into the same issue. If you by chance have solved this in another way, please post your findings here. Jenkins Environment Variables not available in Tests Hi, I'm using Jenkins to trigger scheduled tests and have recently started to use parameters in Jenkins. The parameters are set as environment variables by Jenkins and can easily be accessed by scripts executed on the Jenkins slave but not from the tests run by TestExecute in the same job. I need to parameters to be able to control which test system I should access from my tests. Sure I could copy the tests, one for each target, and hard code the target in each test, but that would quickly lead to a maintenance nightmare, thus I thought of using Jenkins parameters (and Multi-configuration variables) to do the job for me. Anyone tried this and found a solution to get this working? My setup is as follows: Jenkins, TestComplete Jenkins plugin, Java Web Start as service (on Jenkins slaves), TestExecute, Test written in python. Issue filed in support request: Case #00181940: "Environment variables form Jenkins not available in TestExecute" BR, Johan SolvedRe: ProjectSuite.TestItems.Current Fails 'Project.TestItems.Current' and 'ProjectSuite.TestItems.Current' is not the same and does not even have the same interface. There are no 'ProjectName' property on the TestItem, it is only named 'Name'... I would like to know the Name of the currently running project (and test file/function) but that seems not to be possible... - Johan ProjectSuite.TestItems.Current Fails Hi, When trying to use 'ProjectSuite.TestItems.Current' I get a runtime exception message "The parameter is incorrect". Anyone knows how to work around or why this is happening? current = ProjectSuite.TestItems.Current Log.Message('Current Item', ("Name: {}\n" + "Description: {}\n" + "Location: {}").format(current.ProjectName, current.Description, current.ProjectLocation)) - Johan Re: Starting threads in python!? Ok, got answers back from developers that Log and other TestComplete "global" objects is not thread safe and even they require to be executed from the main thread. Code to block missuse is scheduled for version 11.30. Well, well... I do not give up that easily. Here is a recipie (that needs to be completed) to accomplish just what I am after: from queue import Queue, Empty from threading import current_thread, Thread from time import sleep from random import randint def run(): '''Test function''' def func(item, Log): '''Function that emulates the work that needs to be done for each item''' sleep(randint(1, 5)) # emulate some task Log.Message(item) name = current_thread().getName() Log.Message("{name}: Start!".format(**locals())) source = [] for i in range(20): source.append("This is dummy item nbr {i}".format(**locals())) for_each(source, func) # do the work Log.Message("{name}: Done!".format(**locals())) def for_each(source, func, num_worker_threads=8): '''This method launches num_worker_threads, worker threads that calls the func function for each item in source''' class ThreadDone(object): '''Thread termination marker class''' pass class LogEntry(object): '''Information container to pass a Log entry from a worker thread to the main thread''' def __init__(self, entry, *args, **kwargs): self.entry = entry self.args = args self.kwargs = kwargs def execute(self): '''Executes the Log entry, should only be called from the main thread''' try: getattr(Log, self.entry)(*self.args, **self.kwargs) except NameError: pass # do some error handling!? def worker(handler, in_q, out_q): '''Internal thread worker function''' class LogWrapper(object): '''Wrapper that exposes the Log interface and pases the calls to the main thread''' def __init__(self, queue): self.queue = queue def Message(self, messageText, additionalInformation='', priority=300, attr=None, picture=None, folderId=-1): name = current_thread().getName() messageText = "{name}: {messageText}".format(**locals()) self.queue.put( LogEntry('Message', messageText, additionalInformation, priority, attr, picture, folderId)) log = LogWrapper(out_q) try: while True: item = in_q.get(block=False) try: handler(item, log) # call the external worker except: # make sure to swallow any exceptions # as to not to terminate threads pass # exchange for addequate error handling finally: in_q.task_done() except Empty: # nothing more to do, terminate out_q.put(ThreadDone()) def start_workers(worker, num_worker_threads, in_queue, out_queue, func): worker_args = dict(handler=func, in_q=in_queue, out_q=out_queue) '''Start num_worker_threads worker threads and pass the func and in and out queues to the thread worker function''' for i in range(max(4, min(num_worker_threads, 16))): t = Thread(target=worker, kwargs=worker_args) t.daemon = True # set as backgound thread t.start() def join_workers(num_worker_threads, in_queue): '''Wait for all threads to complete, while handling all LogEntries''' while num_worker_threads: item = in_queue.get() if isinstance(item, ThreadDone): num_worker_threads -= 1 # track each terminated thread elif isinstance(item, LogEntry): item.execute() # write to the Log in_queue.task_done() inQ = Queue() outQ = Queue() for item in source: outQ.put(item) start_workers(worker, num_worker_threads, outQ, inQ, func) join_workers(num_worker_threads, inQ) Hope that you find this usefull... BR, Johan Re: Starting threads in python!? Ok, some more digging. I created a small test script and ran it in python (using Eclipse and the prompt). from queue import Queue from threading import current_thread, Thread from time import sleep from random import randint def run(): source = [] for i in range(20): source.append("This is dummy item nbr {i}".format(**locals())) run_test(source) print("Done!") def run_test(source, num_worker_threads=8): def worker(): name = current_thread().getName() while True: item = q.get() sleep(randint(1, 5)) # emulate some task print("{name}: {item}".format(**locals())) q.task_done() q = Queue() for item in source: q.put(item) for i in range(max(4, min(num_worker_threads, 16))): t = Thread(target=worker) t.daemon = True t.start() # here it hangs on the second pass q.join() if __name__ == '__main__': run() This yields the following output: Thread-7: This is dummy item nbr 6 Thread-3: This is dummy item nbr 2 Thread-8: This is dummy item nbr 7 Thread-1: This is dummy item nbr 0 Thread-6: This is dummy item nbr 5 Thread-2: This is dummy item nbr 1 Thread-7: This is dummy item nbr 8 Thread-8: This is dummy item nbr 10 Thread-1: This is dummy item nbr 11 Thread-4: This is dummy item nbr 3 Thread-5: This is dummy item nbr 4 Thread-8: This is dummy item nbr 15 Thread-6: This is dummy item nbr 12 Thread-3: This is dummy item nbr 9 Thread-2: This is dummy item nbr 13 Thread-8: This is dummy item nbr 19 Thread-5: This is dummy item nbr 18 Thread-4: This is dummy item nbr 17 Thread-7: This is dummy item nbr 14 Thread-1: This is dummy item nbr 16 Done! Executing the run() function from TestComplete, hangs TestComplete. Pausing or Stopping the execution does not respond. Stepping the script in the debugger it hangs on the second pass on row 31, 't.start()'. I will file this with support as Tanya suggested. BR, Johan Starting threads in python!? Hi, Have anyone used pythons threading.Thread and Queue in TestComplete? I can not get it to work, test runner hangs on Thread.start() Here is an example of what I'm trying to accomplish def ForEachInParallell(items, func, args, num_worker_threads=8): def worker(args): while True: i = q.get() func(i) q.task_done() q = Queue() for n in range(min(max(4, num_worker_threads), 16)): t = Thread(target=worker, kwargs=args) t.daemon = True t.start() # here the debugger hangs for item in items: q.put(item) q.join() After it hangs I have to kill TestComplete and restart... BR, Johan SolvedRe: TestedApp.Close return value is None in Python Hi, My bad! :smileyembarrassed: I looked at the wrong Close method... As my example showed I was using the return from TesteApp.Run(), which is a Process object. Process objects do have a Close and Terminate method but they return None. Why they do not return the more accessible True or False is another question. You have to use p.Exists or p.IsOpen to figure out if the call to Close (and Terminate) succeeded in closing the app/process. https://support.smartbear.com/viewarticle/71647/ BR, Johan