A previous post on this subject has been helpful (see How to export TestExecute/TestComplete results to teamcity?)
Right now, our TestComplete solution creates a text file that MSBuild consumes with a Microsoft.Build.Utilities.Task helper that sends the messages back up to TeamCity. However, I'm wondering if we can do better.
The TeamCity help topic (http://confluence.jetbrains.com/display/TCD65/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ServiceMessages) says, messages "should be printed into standard output stream of the build". What I'm trying to figure out is, can I directly access that stream from the TestComplete script?
I was hoping that it would be something as simple as:
dotNET.System.Console.WriteLine_11("##teamCity[testSuiteStarted name='Foo']");
But that is obviously not giving me the correct output stream. Thoughts? Can it be done?
The issue you are experiencing is that TestComplete does not support writing to the standard output stream, even if you invoke the CLR Console.WriteLine, you are writing to the process named tcHostingProcess.exe in which all CLR objects exist.
In order to work around this, you need a console application running that can accept messages from your TestComplete project. There are a number of ways to do this, but here is a proposed solution using TCP/IP for the necessary IPC.
In TeamCity
In the TeamCity build steps, you want the TestComplete or TestExecute process to launch without holding up the build script and then to launch a custom console application which will receive the messages from TestComplete.
start TestComplete.exe [arg1] [arg2] ...
TCConsoleHost.exe
Console Host Application
The console host program will start a TcpListener, and once a client connects, it will read messages from the resulting NetworkStream object and print them to the console. This program will continue until there is an error in reading from the stream (i.e. TestComplete has exited).
class Program
{
static void Main(string[] args)
{
TcpListener listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 9800);
listener.Start();
TcpClient client = listener.AcceptTcpClient();
NetworkStream stream = client.GetStream();
BinaryReader reader = new BinaryReader(stream);
while (true)
{
try
{
string message = reader.ReadString();
Console.WriteLine(message);
}
catch
{
break;
}
}
}
}
Message Client Class
Likewise, we can create a TcpClient which can connect to our listening process and relay messages. The real trick here is to wrap this in a static class with a static constructor so that once TestComplete loads the CLR bridge, it will automatically connect and be ready to send the messages. This example has a TeamCity service message function SendMessage which automatically formats the message (including escaping single quotes).
public static class TCServiceMessageClient
{
static BinaryWriter writer;
static NetworkStream stream;
static TCServiceMessageClient()
{
TcpClient client = new TcpClient();
client.Connect("127.0.0.1", 9800);
stream = client.GetStream();
writer = new BinaryWriter(stream);
}
public static void SendMessage(string message)
{
writer.Write(string.Format("##teamcity[message text='{0}'", message.Replace("'","|'")));
}
}
In TestComplete
Now, since the client will automatically connect when the CLR bridge is loaded, the only code necessary in TestComplete is:
dotNET["TCServiceMessageClient"]["TCServiceMessageClient"]["SendMessage"]("Hello TeamCity!");
Additional Notes
There are a few caveats with the above code, namely timing, reconnect, etc. A deployed solution should have better error handling of the network conditions. Additionally, it may be more desirable that the TCMessageHost application actually launches TestComplete directly with a System.Process object so that it can more reliably wait for the application to exit.
I'm working with TeamCity and TestComplete as well. I ran into the exact same problem, and you can't write to the console no matter what you try to do, at least not that I've found. I even tried writing a C# app that I used the CLR bridge in TestComplete to talk to it, and still nothing.
What we ended up doing was to create batch file that handles the TestExecute call. We then call the batch file from TeamCity. To call TestExecute use this (with your pjs file and /p specific to your tests):
start /wait TestExecute "{TestCaseID}.pjs" /r /e /p:"{TestCaseID}" /silentmode /forceconversion
Then we check the ERRORLEVEL property returned by TestExecute. A level of 2 means that the test execution failed. In that case, we print the following with an echo statement:
##teamcity[testFailed name='{TestCaseID} - {TestName}' message='TestExecute reported a failure' details='See artifacts']
After TestExecute closes, it will attempt to open the log file. We have our build servers set so that mht files are opened by the calculator since they take a while to open (set it as the default in the Windows Right-Click -> Open With menu). So, after TestExecute completes, it opens the calculator, then our batch file just kills the calculator using taskkill.
We then copy the result file from TestExecute into a specified location (this is a separate executable that we wrote). The we finish the test execution and publish our artifacts to TestExecute:
echo ##teamcity[testFinished name='{TestCaseID} - {TestName}' duration='%milliSecondsElapsed%']
echo ##teamcity[publishArtifacts 'C:\BuildResults\{GroupName}\{TestCaseID}\*.mht']
One thing to note: We were never able to get TestExecute to reliably run a single test at a time, so we actually use a list of our test cases to generate separate pjs and mds files for each of our test cases. Then we use those generated pjs and mds files in TestExecute. That's where the {GroupName}, {TestCaseID}, and {TestName} variables from above come from. Those are specific to our implementation, but you may need different indicators there.
Hope this helps!
If you are using TestExecute this has become "Relatively" simple recently
Execute TestExecute with the following parameters:
/exportlog:"log\Index.html" /SilentMode /DoNotShowLog
For a full rundown of TestExecute parameters check: https://support.smartbear.com/testexecute/docs/running/automating/command-line/command-line.html
Setup your TestComplete project with a build level report:
Please be aware it is case sensitive
On your build configuration, in the general settings tab, export the generated log folder as an artifact.
Once the build has run, you will be able to see the test log embedded within TeamCity:
This is using TestComplete V14 and TeamCity 2019.1
Related
How could LeanFT check licensing status, when JAR file is generated from a LeanFT project and executed without use of an IDE? In this case LeanFT runtime engine isn't started and URL of license server is not stored in jar file.
LeanFT is more than just that .jar file, and the engine logic takes place somewhere else. Roughly, LeanFT consists of two main parts:
LeanFT client
is the SDK with all the tests. In your case, a .jar file, but could've been a .cs or .js test and would have acted just the same.
has code like Browser.launch and Element.click.
these are commands that are sent to the LeanFT engine
LeanFT engine
among others, is a websocket server that listens to commands, interprets and executes them
The whole journey a command makes is roughly something as follows:
LFT.init is executed somewhere in the code.
It initiates the connection with the right socket server, configured either in a properties file (for java, it is leanft.properties file), or at runtime, via a configuration object (for java, it is a ModifiableSDKConfiguration object). Some minimal guidance regarding this configuration can be found here
this server can be on any computer on the accessible network, but the engine must be there too! (there are a lot of details regarding this here)
Without this command, the test will fail because any command (like click) can't execute as there is no WS connection
Element.click is executed somewhere later in the code
SDK constructs and sends a message to the engine (through websocket connection)
The engine checks if it has a valid license and if all good it performs the command.
Visualized, it is something like this:
I am trying to build a windows service that automates the running of an 3rd party application, let's call it BlackBox.exe. BlackBox.exe runs fine when run from the current user's session but fails when executed from the service. BlackBox.exe has a UI but it can be automated by passing it command line parameters. In the automated mode it shows some UI, reads input files, writes output files and then exits without any user interaction. We only have binaries for BlackBox.exe.
The service is configured to use the same user as BlackBox.exe was installed and registered under.
I've run a comparison of a the events captured by Process Monitor interactive session vs service session. There's no registry or file operations that are failing for the service session and succeeding for the service session. Notably, the registry keys for the license activation are read successfully in both cases.
When run from the service BlackBox.exe is visible in the Task Manager with 0% cpu and will remain there until killed.
I guess the lack of access to the desktop is causing BlackBox.exe to fail - maybe there's a way to fool BlackBox.exe to think it has access to the desktop without having a user logged in?
How can I run BlackBox.exe from a service?
UPDATE:
If I:
start the "Interactive Services Detection" service,
click "View Message" from the Interactive Services Detection dialog,
watch BlackBox.exe gui do its processing until I see the Interactive Serivces Detection message "the application is no longer requesting your attention"
click "Return Now"
...it works fine. So it might be related to Session 0 isolation
Can you essentially run a popup blocker against this? The assumptions here are that that CloseMainWindow() will have the same effect as "View Message", and that you allow the service to interact with the desktop. Sample code below; adapt to your particular scenario and run as a separate thread from your service.
public class Program
{
public static void Main(string[] args)
{
while (true)
{
DestroyAllBobs();
Thread.Sleep(100);
}
}
private static void DestroyAllBobs()
{
Process[] bobs = Process.GetProcessesByName("robert");
foreach (Process bob in bobs)
{
if ("Microsoft Visual C++ Runtime Library".Equals(bob.MainWindowTitle))
{
bob.WaitForInputIdle();
if ("Microsoft Visual C++ Runtime Library".Equals(bob.MainWindowTitle)
&& "robert".Equals(bob.ProcessName))
{
try
{
bob.CloseMainWindow();
}
catch (Exception)
{
}
}
}
}
}
}
I am new to ClearCase trigger. My requirements include the following point:
When user is trying to check in a file using CCRC I need to validate the code being checked in using a PMD tool.
So I need to write a trigger which calls this PMD tool (accessble by CC server) and validate the code being checked in and if code is fine, then I can proceed. Otherwise it should throw error.
Also I need to know how triggers are installed.
Since CC server is not on my local and currently in use by other team mates, I think I need to get it on local to test this. Otherwise it will give issue to others if I test it directly there.
How would you address those points?
A good source for "hooks" (called trggier) for CCRC is the IBM article "Writing triggers for the ClearCase Remote Client" (for CCRC 7.x, which is different from ClearTeam explorer 8.x)
The main issue is that you cannot use clearprompt (which is a full clearcase command, not available with a CCRC client).
See this script for an example on how to write a trigger which detects a CCRC environment.
$ppid=$ENV{"CLEARCASE_PPID"};
$taskline = `tasklist | findstr $ppid`;
$taskname = substr ($taskline,0,index($taskline,"exe")+3);
if ($taskname eq "clearexplorer.exe")
{
...
}
else
{
print STDERR $outtext;
}
I am debugging a lotus script agent using debug a lotus script. Agent is debugging fine but I have another lotus script agent inside that and my debugger is not going to that code line by line.Please help me how to do this.
Thanks in advance.
An agent, that is called in script from another agent runs in the background. These agents can not be debugged easily. If the called agent runs on the server, you can use the remote debugger, to debug that agent: you have to enable it in the server document, start the remote debug task, and enable remote debugging in the properties of the called agent. Then you have to be fast. You define a delay that each agent waits for the debugger to attach, before it really starts with its code. During this time, you have to start the remote debugger, open the database and select the agent to debug... Quite painful. And the normal Debugger has to be off and the agent you startet has to run in client background mode, otherwise you will not be able to switch to remote debugger...
If both agents are LotusScript and it is not needed, that they:
Run with different rights or
Run on different servers,
then there normally is no need for an agent calling another agent.
Use script- libraries and subs / functions instead, then you do not need two agents...
I recommend to you use a simple log in the second agent. You can use NotesLog (look at Domino Developer's Help), or you can write your own class as you need it.
In my apps, I use a LotusScript framework, written by me. In that framework, I have a CS_Log class, who connects to a LogAgents.nsf database and writes all in simple documents. Also, I have a CS_Document class, with a Dump method, who writes the full content of a document, for example.
The most times, debugging it's the best option. But in cases like this, I prefer to write all in a log.
I am trying to run unmodified reports using batch processing in Microsoft Dynamics AX 2009. I have set up my configuration, and set up an AOS printer to run the report on. When I send a report to the batch queue, it immediately has an error when it begins execution.
The error is as follows:
Error executing code: SysGlobalCache object not initialized.
(S)\Classes\SysGlobalCache\get (S)\Classes\ClassFactory\reportRunClass
- line 14 (S)\Classes\RunBaseReport\makeReportRun - line 19 (S)\Classes\RunBaseReport\unpack - line 31
(S)\Classes\RunbaseReportStd\unpack - line 26
(S)\Classes\BatchRun\runJobStatic - line 27
I have tried running three different reports: Customer, Vendor, and Purchase Lines. I get the same error every time.
Any suggestions?
We faced a similar problem at my work, but didn't want to rely on having to set up the legacy batch processing method, suggested previously. Luckily in our case, it wasn't a requirement that the report actually be printed to hard-copy. So rather than try to send the report to a printer, you can run it to a file (ASCII, PDF, etc).
The batch server can process these, but since you'll need to specify a place to save the file, watch out for the following:
Be sure to use a UNC file path the path you wish to save to, otherwise you may get the following error: "Target file must be in UNC format."
Also be sure the necessary permissions have been applied to allow writing to that location, otherwise you'd get an error such as: "Unable to open file "
I believe the issue is that the batches are trying to process server code, and the reports are meant to run client side. Try the work around at this URL:
http://blogs.msdn.com/b/emeadaxsupport/archive/2009/06/16/how-to-run-client-batches-on-ax-2009.aspx
The gist is this, you create a batch group called "Client" or whatever, assign it to a batch server, then you run the legacy batch processor on the group. This might work for you.
Another option is to change the report to run on the server.
You'll need to check the menu item and make sure it's set to run on server.
It's a property on the menu item.
When you add a report to the batch, take a look at the batch inquiry screen.
Select the batch job - then click 'tasks'. If the task shows 'Run Location' = client, it won't run in the server-based batch framework.
Rob.
I was getting similar error. I restarted AOS and SQL reporting service and it worked all fine. Hope this helps.