How to group test cases in TestNG? - webdriver

I want to launch two browsers at a time with different parameters. I've written Test suite like below. but, it is launching 8 browsers at a time (As I've mentioned parallel='tests' it is launching browsers for all classes available in that test)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite thread-count="2" name="Suite" parallel="tests">
<test name="Test1" preserve-order="true">
<parameter name="propertyFileName" value="Constants.properties"/>
<classes preserve-order="true">
<class name="com.test.TestCase1"/>
<class name="com.test.TestCase2"/>
<class name="com.test.TestCase3"/>
<class name="com.test.TestCase4"/>
</classes>
</test> <!-- Test -->
<test name="Test2" preserve-order="true">
<parameter name="propertyFileName" value="Constants2.properties"/>
<classes preserve-order="true">
<class name="com.test.TestCase5"/>
<class name="com.test.TestCase6"/>
<class name="com.test.TestCase7"/>
<class name="com.test.TestCase8"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
Is there any way to launch only two browsers at a time ?
I want to group Test cases such that while running in parallel (only two test cases at a time) both should take Constants from different property file.
EDIT-I
TestCase1.java
public class TestCase1
{
private WebDriver driver;
CommonMethods comObj;
StringBuffer failureMsgs;
#Parameters({"propertyFileName"})
#BeforeTest
public void beforeTest(String pname) throws Exception
{
comObj=new CommonMethods(pname);
driver=new FirefoxDriver();
comObj.login(driver, comObj.userName,comObj.password);
}
#Test
public void f()
{
try
{
}
catch(Exception e)
{
e.printStackTrace();
}
}
#AfterTest
public void afterTest()
{
System.out.println("Inside after method");
driver.quit();
}
}

The problem is with your setup and tear down code. You are using #Aftertest and before test. Your browsers would only shutdown when aftertest runs which would be only twice. Either you should use #afterclass or #aftermethod and corresponding beforemethods. testng is workin correctly coz it runs all your before test methods at the start, thus launching 8 browsers first.

Related

NLog ApplicationInsightsTarget unable to read application insights key from appsettings.json

I am trying to read the application insights instrumentation key from appsettings.json file in my ASP.NET Core 3.1 Web Application but all my tries went in vain so far as the target is still showing as unconfigured.
If I add the key directly in ApplicationInsightsTarget, then it is working fine.
Here is the content of appsettings.json file:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"AppInsightsKey": "Instrumentation-Key-From-Azure-Application-Insights-Resource"
}
Here is the content of nlog.config file:
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
throwConfigExceptions="true"
internalLogLevel="info"
internalLogFile="c:\temp\internal-nlog-AspNetCore3.txt">
<!-- enable asp.net core layout renderers -->
<extensions>
<add assembly="Microsoft.ApplicationInsights.NLogTarget" />
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<!-- the targets to write to -->
<targets>
<!--Console Target for hosting lifetime messages to improve Docker / Visual Studio startup detection -->
<target xsi:type="Console" name="lifetimeConsole" layout="${configsetting:item=AppInsightsKey} ${level:truncate=4:lowercase=true}: ${logger}[0]${newline} ${message}${exception:format=tostring}" />
<target name="aiTarget" xsi:type="ApplicationInsightsTarget"
layout="${date:format=yyyy-MM-dd HH\:mm\:ss}: [LOCAL] - ${level} - ${message}${exception:format=ToString}">
<instrumentationKey>${configsetting:item=AppInsightsKey}</instrumentationKey>
<contextproperty name="threadid" layout="${threadid}" />
</target>
</targets>
<!-- rules to map from logger name to target -->
<rules>
<logger name="*" minlevel="Trace" writeTo="lifetimeConsole" />
<logger name="*" minlevel="Trace" writeTo="aiTarget" />
</rules>
</nlog>
As you can see from above, I was trying to grab the application insights key from appsettings.json file by ${configsetting:item=AppInsightsKey}, but in all occasions it's coming as empty.
I've tried with ${configsetting:name=AppInsightsKey} , which didn't help either.
This is the program.cs file content
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NLog.Web;
using System;
namespace ASPNETCoreWebAppNLogAppInsightsDemo
{
public class Program
{
public static void Main(string[] args)
{
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
try
{
logger.Debug("init main");
CreateHostBuilder(args).Build().Run();
}
catch (Exception exception)
{
//NLog: catch setup errors
logger.Error(exception, "Stopped program because of exception");
throw;
}
finally
{
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
NLog.LogManager.Shutdown();
}
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
})
.UseNLog(); // NLog: Setup NLog for Dependency injection
}
}
Then I've tried to embed the key in the console target layout, just to ensure nlog is able to read it correctly, which to my surprise is working perfectly fine. So, looks like the issue is with ApplicationInsightsTarget only.
I know, I can pull it from Environment variables and hence in Azure App service it is not required to read from appsettings.json, but I would like to understand about this behavior since already spent too much time fixing myself :-)
Any help will be appreciated.
Try replacing the old code:
var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
With this new code:
var logger = LogManager.Setup()
.LoadConfigurationFromAppSettings()
.GetCurrentClassLogger();
The new code will load the appsettings.json, and sure that ${configsetting} are available during initialization of NLog Targets.

Wait for asynchronous logging to finish before Thread ends slf4j/log4j2

I'm using an asynchronous database logging setup with slf4j/log4j2. All is working as expected.
The only drawback is, that sometimes when the server is shut down the logger has not completed writing to the database (e.g. if there was a burst before shutdown).
I get:
WARN AsyncLoggerConfigDisruptor: shutdown timed out after 0
MILLISECONDS Log4j2-TF-1-AsyncLoggerConfig-1 ERROR Attempted to append
to non-started appender databaseAppender
And I lose everything that was in the logger-buffer.
Is there a way in slf4j or log4j2 to wait for the asynchronous logger to finish (e.g. a blocking call at the end of a task)?
Or at least to get the size of the buffer, that still needs to be written?
Currently, I use a setup with synchronous file logger and an asynchronous database logger, so the data is still in the file...
--> Edit 02/28/19
Here is a quick and dirty example code:
protected static final Logger logger = LoggerFactory.getLogger(App.class);
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
Runnable task = new TestLogging(i);
executor.submit(task);
}
executor.shutdown();
System.out.println("Done");
//LogManager.shutdown();
}
private static class TestLogging implements Runnable {
private int i;
public TestLogging(int i) {
this.i=i;
}
public void run() {
// Generate a big string for DB test
StringBuffer b=new StringBuffer();
IntStream.range(0, 1000).parallel().forEach(i -> b.append(UUID.randomUUID().toString()));
// Writing to context for logging
MDC.put("test", "test"+i);
MDC.put("test1", b.toString());
// Log 1000 lines
IntStream.range(0, 1000).forEach(j -> logger.error("Exception " + j + "-"+ i, new RuntimeException()));
}
}
The configuration xml:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<File name="MyFile" fileName="all.log" immediateFlush="false"
append="false">
<PatternLayout
pattern="%d{yyy-MM-dd HH:mm:ss.SSS} tx.id=%X{test} tx.content=%X{test1} [%t] %-5level %logger{36} - %msg%n" />
</File>
<JDBC name="databaseAppender" tableName="log_test">
<PoolingDriver connectionString="jdbc:oracle:thin:#centos.fritz.box:1521:orcl" userName="test" password="test" driverClassName="oracle.jdbc.driver.OracleDriver"/>
<Column name="LOG_ID" pattern="%u" />
<Column name="ENTRY_DATE" isEventTimestamp="true" />
<Column name="LOGGER" pattern="%logger" />
<Column name="LOG_LEVEL" pattern="%level" />
<Column name="MESSAGE" pattern="%m" />
<Column name="EXCEPTION" pattern="%throwable" />
<Column name="ID" pattern="%X{test}" />
<Column name="XML" pattern="%X{test1}" />
</JDBC>
</Appenders>
<Loggers>
<AsyncRoot level="info">
<AppenderRef ref="databaseAppender" />
</AsyncRoot>
<Logger name="com.test" level="trace" includeLocation="true">
<AppenderRef ref="MyFile" />
</Logger>
</Loggers>
</Configuration>
And for Oracle the DDL:
CREATE TABLE "TEST"."LOG_TEST"
( "LOG_ID" VARCHAR2(100 BYTE),
"ENTRY_DATE" TIMESTAMP (6),
"LOGGER" VARCHAR2(100 BYTE),
"LOG_LEVEL" VARCHAR2(100 BYTE),
"MESSAGE" CLOB,
"EXCEPTION" CLOB,
"ID" VARCHAR2(20 BYTE),
"XML" CLOB,
PRIMARY KEY ("LOG_ID"))
If I use the
LogManager.shutdown();
The logging doesn't even start. Without, depending on the DB, I get about 500-1000 lines in the DB, before the error appears.
The logging in the real database will be much more sparse, this is just a worst-case test... and as mentioned, the logging in the file works. It would just be nice, to have a consistent logging in DB and file, even if the service is shut down.

Use Symfony service in phpunit

I would like to test my DAO service.
The problem is that nothing append when I execute my test. No test is executed.
But I'm sur that the config file phpunit.xml.dist is ok, beause if I make a mistake in the "use" line for exemple, the test show me the errors.
So I need your help..
My first test :
namespace RepositoryBundle\Tests\DAO;
use RepositoryBundle\Entity\User;
use RepositoryBundle\Enum\RoleEnum;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
class UserDAOTest extends KernelTestCase
{
private $userDAO;
private $logger;
public function setUp()
{
self::bootKernel();
$this->userDAO = static::$kernel->getContainer()->get('repository.userDAO');
$this->logger = static::$kernel->getContainer()->get('logger');
$logger->notice('Show the log'); // Nothing is in my console.. (I configure Monolog to display in the console)
}
public function testTRUC()
{
//Stupid test but not executed !!!???
$i = 1;
$this->assertTrue($i == 1);
}
public function testCreate()
{
//Real test but not executed !!!???
$user1 = new User();
$user1->setName("TestName");
$user1->setEmail("TestEmail");
$user1->setPassword("TestPassword");
$user1->setMemberNumber(12345);
$user1->setAdmin(true);
$user1->setRole(RoleEnum::User);
$user1 = $UserDAO->save($user1);
$this->assertTrue($user1->getId() > 0);
$this->assertEquals("TestName", $user1->getName());
$this->assertEquals("TestEmail", $user1->getEmail());
$this->assertEquals("TestPassword", $user1->getPassword());
$this->assertEquals(12345, $user1->getMemberNumber());
$this->assertEquals(true, $user1->isAdmin());
$this->assertEquals(RoleEnum::User, $user1->getRole());
}
phpunit.xml.dist
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="phpunit.xsd"
bootstrap="bootstrap.php.cache"
backupGlobals="false"
verbose="true">
<testsuites>
<testsuite name="Project Test Suite">
<directory>../src/*Bundle/Tests</directory>
</testsuite>
</testsuites>
<php>
<const name="PHPUNIT_TESTSUITE" value="true"/>
</php>
</phpunit>
When I execute the command :
A screen of the console
Thanks for your help. I'm new with Symfony and PHPUnit and I lost a lot of time with this kind of problems..
Please correct me if I'm wrong, but your test is located in src\RepositoryBundle\Tests\DAO and you are executing phpunit on folder app...
Try phpunit(Edit of course c option requires an argument :/) and it should work.
You configuration is configured to look up '../src/*Bundle/Tests'. If you provide the app folder as the place to to look up test, then your configuration won't be considered.

Inline MS Build Task in separate AppDomain

End Goal:
I would like to have a custom build task that takes my compiled assembly, and extracts all instances of a particular attribute for automated documentation and uninstallation. (In this case the GUID attribute for a set of COM-visible types).
Problem:
After reading some examples, the prospect of using an Inline Build Task was rather tempting. However, my task needs to reflect across the built assemblies and extract certain meta-data from it (specifically attributes).
The catch is reflecting over the assembly will lock the output file until the AppDomain is unloaded, which in this case appears to be only when Visual Studio is closed. The result: the build can only once per session.
I see that there exists special build task classes, namely AppDomainIsolatedTask but I can find no examples or evidence that this class can be utilized for an inline task.
Question:
Is it possible to run an Inline Build task in a separate AppDomain? If so, then how?
Code Sample: (as short as possible)
<UsingTask TaskName="InDomainTask" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<Task><Code Type="Class" Language="cs"><![CDATA[
public class InDomainTask : Microsoft.Build.Utilities.Task
{
public override bool Execute()
{
Log.LogMessage("InDomainTask AppDomain.Id = " + System.AppDomain.CurrentDomain.Id);
return true;
}
}
]]></Code></Task>
</UsingTask>
<UsingTask TaskName="OutDomainTask" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<Task><Code Type="Class" Language="cs"><![CDATA[
[Microsoft.Build.Framework.LoadInSeparateAppDomain]
public class OutDomainTask : Microsoft.Build.Utilities.AppDomainIsolatedTask
{
public override bool Execute()
{
Log.LogMessage("OutDomainTask AppDomain.Id = " + System.AppDomain.CurrentDomain.Id);
return true;
}
}
]]></Code></Task>
</UsingTask>
<Target Name="AfterBuild" AfterTargets="Compile">
<InDomainTask />
<OutDomainTask />
</Target>
The build output of these is:
1> InDomainTask AppDomain.Id = 1
1> OutDomainTask AppDomain.Id = 1
No, it's not possible.
Inline tasks use the CodeTaskFactory to create the task, and if you take a look at the code on GitHub, you will see that after compiling an assembly that contains the code, an instance of the task is creating using Activator.CreateInstance. This means it is always created in the same AppDomain as MSBuild.
Compare that to pre-compiled tasks, which use the TaskLoader class to create an instance of the task, and that TaskLoader looks for the LoadInSeparateAppDomainAttribute on the task type and creates an instance in a separate AppDomain if it's found.
The easiest solution is to turn your inline code into a pre-compiled task. It's really easy to do:
Create a class library project
Reference Microsoft.Build.Utilities.
Create a class for your task.
Compile the project.
Replace your UsingTask element with one that specifies the assembly that contains the tasks.
Here's an example:
Your class library that contains the tasks:
public class InDomainTask : Microsoft.Build.Utilities.Task
{
public override bool Execute()
{
Log.LogMessage(System.AppDomain.CurrentDomain.FriendlyName);
return true;
}
}
public class OutDomainTask : Microsoft.Build.Utilities.AppDomainIsolatedTask
{
public override bool Execute()
{
Log.LogMessage(System.AppDomain.CurrentDomain.FriendlyName);
return true;
}
}
Your MSBuild file:
<UsingTask TaskName="InDomainTask" AssemblyFile="path\to\the\class\library.dll"/>
<UsingTask TaskName="OutDomainTask" AssemblyFile="path\to\the\class\library.dll"/>
<Target Name="AfterBuild" AfterTargets="Compile">
<InDomainTask/>
<OutDomainTask/>
</Target>
This outputs:
MSBuild.exe
taskAppDomain (in-proc)
Alternatively, you can run your job in separate MsBuild.exe process using Exec command and pass in same current targets file and needed properties.
<Project ToolsVersion="15.0" DefaultTargets="RunCodeFromTargetPath" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<RunCodeFromTargetPathAfterTargets>PrepareForRun</RunCodeFromTargetPathAfterTargets>
</PropertyGroup>
<Target Name="RunCodeFromTargetPath" AfterTargets="$(RunCodeFromTargetPathAfterTargets)">
<PropertyGroup Condition="'$(PlatformTarget)' == 'x64'">
<MsBuildFolderLocation >\amd64</MsBuildFolderLocation><!--support for x64 only assemblies -->
</PropertyGroup>
<Exec Command=""$(MSBuildBinPath)$(MsBuildFolderLocation)\MSBuild.exe" /target:RunCodeFromTargetPathInternal /p:TargetPath="$(TargetPath.Replace('\','\\'))" "$(MSBuildThisFileFullPath)"" />
</Target>
<Target Name="RunCodeFromTargetPathInternal">
<RunCodeFromTargetPathTask />
</Target>
<UsingTask
TaskName="RunCodeFromTargetPathTask"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<Task>
<Reference Include="$(TargetPath)" />
<Code Type="Fragment" Language="cs">
<![CDATA[
// your code here
]]>
</Code>
</Task>
</UsingTask>
</Project>

how to set isdebugenabled in NLog

I try to find a way to set isdebugenabled false or true in configuration file,
so I can turn it on or off whenever I need. Thanks !
Using a really simple logging setup
<targets>
<target xsi:type="File"
name="debug"
fileName="c:\temp\debug.txt"
layout="${longdate} ${uppercase:${level}} ${message}"
/>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="debug" />
</rules>
And an equally simple code sample
class Program
{
static void Main(string[] args)
{
var logger = new NLog.LogFactory().GetCurrentClassLogger();
if (logger.IsDebugEnabled)
{
logger.Debug("this is a debug message");
}
logger.Debug("this is another debug message");
}
}
When minLevel is set to Debug or Trace, both logger.Debug statements will write to the log. If you raise minLevel to a higher level (Info, Warn, Off) neither statement will be written to the log. logger.Debug checks IsDebugEnabled (which is inferred from the log level).
You can certainly get a performance increase (in cases where you are going to be logging calculated values and not just strings) by checking IsDebugEnabled, and changing minLevel for the logger is the way to toggle this.

Resources