Configuration settings make tests unstable with NCrunch - nunit

I have a problem with tests becoming unstable under NCrunch. It looks like it has to do with some shadow copying issue. My test goes something like this
class SaveViewSettings : ISaveSettings
{
public void SaveSettings()
{
Properties.View.Default.Save();
}
}
[TestFixture]
// ReSharper disable once InconsistentNaming
class SaveViewSettings_Should
{
[Test]
public void Save_Settings()
{
var ctx = Properties.View.Default;
var sut = new SaveViewSettings();
ctx.LeftSplitter = 12.34;
sut.SaveSettings();
ctx.Reload();
ctx.LeftSplitter.Should().Be(12.34);
}
}
When reloading the settings using ctx.Reload() i get
System.Configuration.ConfigurationErrorsException : ...
----> System.Configuration.ConfigurationErrorsException...
(C:\...\AppData\Local\Remco_Software_Ltd\nCrunch.TestRunner.AppDom_Url_q2piuozo0uftcc2pz5zv15hpilzfpoqk\[version]\user.config...)
A similar problem has been raised on the NCrunch forum about 3 months ago: Unrecognized configuration section userSettings

You might get similar errors with NCrunch when working on multiple solutions with application settings.
I think this might root down to NCrunch always using the same product and user name when shadow building so that all configuration settings are mapped to the same user.config file path.
It seems that by now there is no known solution to this. A work around is to manually delete the user config in
%LOCALAPPDATA%\Remco_Software_Ltd\nCrunch.TestRunner.AppDom_...\user.config`.
Note that the usual way to do this ctx.Reset() might fail as well, so you really have to locate and delete the user.config yourself using ConfigurationManager.
I have automated this work around by adding the following code which stabilizes the test with NCrunch
[Test]
public void Save_Settings()
{
#if NCRUNCH
// Every once in a while NCrunch throws ConfigurationErrorException, cf.:
// - http://forum.ncrunch.net/yaf_postsm7538_Unrecognized-configuration-section-userSettings.aspx
// - http://www.codeproject.com/Articles/30216/Handling-Corrupt-user-config-Settings
// - http://stackoverflow.com/questions/2903610/visual-studio-reset-user-settings-when-debugging
// - http://stackoverflow.com/questions/9038070/how-do-i-get-the-location-of-the-user-config-file-in-programmatically
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
if (File.Exists(config.FilePath))
File.Delete(config.FilePath);
#endif
...
Over the past few years i came to consider .NET configuration settings as a kind of legacy feature. It was introduced with .NET 2.0 and was great at the time but it has some issues that you need to be aware of. Maybe it is a good idea to look for alternatives or abstractions like e.g. HumbleConfig which makes it easy to switch.

Related

How to run code before/after cucumber suite?

I'm trying to figure out how to run some code before and after all my cucumber tests run.
I've been tracking down a bug for a few days where some our processes create jobs on a server, and don't properly clean it up. It's easy to miss so ideally I don't want engineers to have to manually add a check to every test.
I was hoping there'd be a way to put a hook in before any tests ran to cache how many jobs exist on the server, then a hook at the end to ensure that the value hasn't changed.
I know this isn't really the best way to use cucumber, as that is more of a system test type thing to do, but doing it this way would be the best way to fit it into the existing infrastructure.
Use #BeforeClass and #AfterClass annotations in your run file.
#RunWith(Cucumber.class)
#Cucumber.Options(
format = {"json", "<the report file>"},
features = {"<the feature file>"},
strict = false,
glue = {"<package with steps classes>"})
public class TestRunFile {
#BeforeClass
public static void getJobNumbersOnServerBeforeStarting() {
//Implement logic
}
#AfterClass
public static void getJobNumbersOnServerAfterCompletion() {
//Implement logic
}
}
How about using tagged hooks.
#Before("#jobCheck")
public void beforeScenario() {
// actions
}
#After("#jobCheck")
public void afterScenario() {
// actions
}
And then for each scenario that requires this check, add #jobCheck before the Scenario definition as below.
Feature: Some feature description
#jobCheck
Scenario: It should process a sentence
// The steps
More on JVM hooks here: https://zsoltfabok.com/blog/2012/09/cucumber-jvm-hooks/

Eloquent error: A facade root has not been set

I have been using Eloquent as a standalone package in Slim Framework 2 successfully.
But now that I want to make use of Illuminate\Support\Facades\DB since I need to show some statistics by getting the info from 2 tables and using a Left Join and a Counter from the database like this:
use Illuminate\Support\Facades\DB;
$projectsbyarea = DB::table('projects AS p')
->select(DB::raw('DISTINCT a.area, COUNT(a.area) AS Quantity'))
->leftJoin('areas AS a','p.area_id','=','a.id')
->where('p.status','in_process')
->where('a.area','<>','NULL')
->orderBy('p.area_id');
I get the following error:
Type: RuntimeException
Message: A facade root has not been set.
File: ...\vendor\illuminate\support\Facades\Facade.php
Line: 206
How can I solve it?
So far I have found out, in this link that I need to create a new app container and then bind it to the Facade. But I haven't found out how to make it work.
This is how I started the rest of my Eloquent and working fine:
use Illuminate\Database\Capsule\Manager as Capsule;
$capsule = new Capsule();
$capsule->addConnection([
'my' => $app->config->get('settings'),
/* more settings ...*/
]);
/*booting Eloquent*/
$capsule->bootEloquent();
How do I fix this?
Fixed
As #user5972059 said, I had to add $capsule->setAsGlobal();//This is important to make work the DB (Capsule) just above $capsule->bootEloquent();
Then, the query is executed like this:
use Illuminate\Database\Capsule\Manager as Capsule;
$projectsbyarea = Capsule::table('projects AS p')
->select(DB::raw('DISTINCT a.area, COUNT(a.area) AS Quantity'))
->leftJoin('areas AS a','p.area_id','=','a.id')
->where('p.status','in_process')
->where('a.area','<>','NULL')
->orderBy('p.area_id')
->get();
You have to change your code to:
$Capsule = new Capsule;
$Capsule->addConnection(config::get('database'));
$Capsule->setAsGlobal(); //this is important
$Capsule->bootEloquent();
And at the beginning of your class file you have to import:
use Illuminate\Database\Capsule\Manager as DB;
I have just solved this problem by uncommenting $app->withFacades(); in bootstrap/app.php
Had the same issue with laravel 8. I replaced
use PHPUnit\Framework\TestCase;
with:
use Tests\TestCase;
Try uncommenting in app.php $app->withFacades();
Do not forget to call parent::setUp(); before.
fails
public function setUp(): void {
Config::set('something', true);
}
works
public function setUp(): void {
parent::setUp();
Config::set('something', true);
}
One random problem using phpUnit tests for laravel is that the laravel facades have not been initialized when testing.
Instead of using the standard PHPUnit TestCase class
class MyTestClass extends PHPUnit\Framework\TestCase
one can use
class UserTest extends Illuminate\Foundation\Testing\TestCase
and this problem is solved.
I got this error after running:
$ php artisan config:cache
The solution for me was to delete the /bootstrap/cache/config.php file. I'm running Laravel 5.5.
The seems to arise in multiple situation, and not just about facades.
I received the following message while running tests using PHPUnit v.9.5.4, PHP v.8.0.3 and Lumen v. 8.2.2:
PHP Fatal error: Uncaught RuntimeException: A facade root has not
been set. in path_to_project/vendor/illuminate/support/Facades/Facade.php:258
And that happened although I had apparently already configured my app.php to enable facades ($app->withFacades();), still I received this error message whenever I tried to run tests using Illuminate\Support\Facades\DB. Unfortunately, none of the other answers helped me.
This error was actually been thrown due to my configs in phpunit.xml, which didn't point to my app.php file, where I actually enabled facades.
I just had to change
<phpunit (...OTHER_PARAMS_HERE) bootstrap="vendor/autoload.php">
to
<phpunit (...OTHER_PARAMS_HERE) bootstrap="bootstrap/app.php">
Hope it helps.
wrong way
public function register()
{
$this->app->bind('Activity', function($app)
{
new Activity;
});
}
right way đź‘Ť
public function register()
{
$this->app->bind('Activity', function($app)
{
return new Activity;
});
}
---------------------------------- don't forget return
Upgrade version for php, I encountered this error while calling the interface.
$ php artisan config:cache
Deleting the /bootstrap/cache/config.php file is a very effective way.
In my project, I managed to fix this issue by using Laravel Dependency Injection when instantiating the object. Previously I had it like this:
$class = new MyClass(
new Client(),
env('client_id', 'test'),
Config::get('myapp.client_secret')
);
The same error message happened when I used Laravel env() and Config().
I introduced the Client and env in the AppServiceProvider like this:
$this->app->bind(
MyClass::class,
function () {
return new MyClass(
new Client(),
env('client_id', 'test')),
Config::get('myapp.client_secret')
);
}
and then instantiated the class like this:
$class = app(MyClass::class);
See more from https://laravel.com/docs/5.8/container .
In my case, for a while a ran a PHP project in PHP version 8, and that time I used some PHP 8 features like param definition and method's multiple return type declarations supported by only PHP 8 and above. When I downgraded from PHP 8 to PHP 7.4 I faced this issue. After removing the return types and param hinting the problems are gone.
Tested on Laravel 8.78
tests/bootstrap.php
<?php
use Illuminate\Foundation\Bootstrap\RegisterFacades;
use Illuminate\Foundation\Bootstrap\LoadConfiguration;
require_once __DIR__ . '/../vendor/autoload.php';
$app = require_once __DIR__ . '/../bootstrap/app.php';
(new LoadConfiguration())->bootstrap($app);// <------- Required for next line
(new RegisterFacades())->bootstrap($app);// <------- Add this line
Here is yet another instance of this error, happened to me after upgrading Laravel 8 to 9.
I had feature tests with a #dataProvider to supply data to those tests. Some of the data supplied by the data provider methods came from an application service. It was being initialised like this:
/**
* #dataProvider myDataProvider
*/
public function testSomeStuff(...)
{
...
}
public function myDataProvider()
{
$myService = app(Service::class); // This is trouble
return [
['test1_data' => $myService::SOME_CONSTANT],
[...],
...
];
}
This worked under Laravel 8, but not in Laravel 9. All other solutions listed in this SO thread were checked and were correctly set up.
The problem is that the application is not being inititialised until after the data provider method is run. It was presumably initialised before this stage in the Laravel 8 install. So app(Service::class) was failing due to it using facades internally.
One workaround could be to force the application to initialise earlier, in the data provider function: $this->createApplication(). I would not recommend this due to potential side effects of the test parts running in the wrong order, though it does appear to work when I tried it.
Best solution is to avoid accessing any part of the application functionality in the data provider methods. In my case it was easy to replace $myService::SOME_CONSTANT with MyService::SOME_CONSTANT after making sure those constants were public.
Hopefully this will help somebody suddenly hitting this problem running feature tests after a Laravel 9 upgrade.
If you recently upgrade Laravel on Homestead & VirtualBox environment or do not find any reason that causing please be sure your Vagrant is up to date.
Referance
I had Taylor lock this thread. The past several replies have restated the solution, which is to Upgrade to Virtualbox 6.x, the thread is locked to prevent other issues that are not related from being dogpiled on here.
#melvin's answer above works correctly.
In case someone is wondering about it, the mistake people do is to choose Yes when VSCode asks them if they are making a Unit Test. Remember, Unit Tests should really be unit tests, independent of other application features (models, factories, routes; basically anything that would require the Laravel app to be fired up). In most scenarios, people really actually want to make Feature Tests and therefore should answer No to the above question. A feature test inherits from Tests\TestCase class (which takes care of firing up Laravel app before running the test) unlike unit tests that inherit from the class PHPUnit\Framework\TestCase which use just PHPUnit and are therefore much faster.
credit with thanks to #Aken Roberts's answer here.
From Laravel Documentation: Generally, most of your tests should be feature tests. These types of tests provide the most confidence that your system as a whole is functioning as intended.

Debug code-first Entity Framework migration codes

I'm using Entity Framework code first in my website and I'm just wondering if there is any way to debug the migration codes. You know, like setting breakpoints and stuff like this.
I'm using Package Manager Console to update the database using Update-Database.
Thanks
I know that EF Code First Migrations is relatively new tool but don't forget about you are still in .NET.
So you can use:
if (System.Diagnostics.Debugger.IsAttached == false)
{
System.Diagnostics.Debugger.Launch();
}
After that you can see your InnerException.
Or you can use try...catch statement like this:
Exception handling Entity Framework
To hit a break point in a db migration set the context to MigrateDatabaseToLatestVersion on initialise.
Database.SetInitializer(new MigrateDatabaseToLatestVersion<EnterContextHere, Configuration>());
Then you just debug as normal (run using f5) and the breakpoint will hit the first time you run the project.
The problem now is that if you debug a second time the migration will not run. This is because the __MigrationHistory table has been updated to say you have migrated to the latest version. To re-test the migration open the package manager console and downgrade to the previous migration:
Update-Database –TargetMigration: ThePreviousMigrationName
My answer might be a bit silly but anyway here it goes.
If you, like me, some times have problems in the Seed() method what I usually do is simply create a public method that calls the Protect Seed().
public void SeedDebug(AppDbContext context)
{
Seed(context);
}
then in my HomeController I call this method in Debug mode.
public class HomeController : Controller
{
var appDb = new AppDbContext();
public ActionResult Index()
{
var config = new Configuration();
config.SeedDebug(appDb);
return View();
}
}
I know it's a bit lame solution, but it's simple and quick.
Of course this has to be done after the model been created.
So step by step:
comment the seed method and execute the update-database to create the model
uncomment the method Seed() and plugin the "hack" I mentioned above.
in the configuration disable Auto migrations
AutomaticMigrationsEnabled = false;//if you have this disabled already skip this step
Debug your application, fix the error and remove the "hack"
Here's a more fail-proof method which will do the trick without much fuss:
Step#1: Place this piece of code right above the migration you want to debug:
public partial class ORACLE_Test : DbMigration
{
public override void Up()
{
if (!System.Diagnostics.Debugger.IsAttached)
System.Diagnostics.Debugger.Launch();
AddColumn("TEST", "UR_USER_ID", x => x.Decimal(nullable: false, precision: 11, scale: 0, storeType: "number"));
AddColumn("TEST", "UR_CLIENT_ID", x => x.Decimal(nullable: false, precision: 11, scale: 0, storeType: "number"));
[...]
}
public override void Down()
{
}
}
Step#2: Compile the project containing your migrations
Step#3: Open a console inside the output directory (/bin/Debug, /bin/Release etc) containing the dll of your migrations
Step#4: Invoke migrate.exe with the /scriptFile parameter to launch the debugger and actually debug the desired db-migration
migrate.exe "Your.Migrations.Assembly.dll" /scriptFile="foo.sql" /verbose /startupConfigurationFile="Your.Migrations.Assembly.config"
Once the debugger-selector dialog pops up pick the visual studio instance that you have already opened.
You could add Console.WriteLine statements to the migration code (not a great solution)
Note, the messages are only shown if you run the migration code using the migrate.exe utility (in pacakges\EntityFramework.x.y.z\tools). They will not display if you run the migration through the Package Manager console.
I've had lots of luck using "Debugger.Launch()" (like in m_david's answer above) elsewhere, but inside of CreateDbContext it seems to somehow both attach, and not attach. What I mean is, it attaches and starts trying to step into .asm files and .cpp files (internal code). If I try to set a breakpoint on a Console.Writeline that I KNOW gets executed afterwards (I can see the output from ANY "dotnet ef migrations COMMAND") it both executes it and never hits the breakpoint.
This is what worked for me instead:
while (!System.Diagnostics.Debugger.IsAttached)
System.Threading.Thread.Sleep(10);
// Breakpoint after this...
You can execute the migration and manually attach using Visual Studio and it will actually let you step through the code like you expect, it's just more of a pain. What I should really try is the combination of both methods...
I also found a neat trick here to get the error details...
Basically, the trick is to grab all the information from an exception, put it in a string and throw a new DbEntityValidationException with the generated string and the original exception.

methodAccessException when passing variables from ViewModel to ViewModel on WP7 using anonymous object (MVVMCross)

I've created an app using MVVMCross, the IOS and Android versions are working but when I tried to "port" to WP7 and I ran into the following problem:
throw methodAccessException.MvxWrap("Problem accessing object - most likely this is caused by an anonymous object being generated as Internal - please see http://stackoverflow.com/questions/8273399/anonymous-types-and-get-accessors-on-wp7-1");
As mentioned in the answer to my other question about this (on Android) you have to set an InternalsVisibleTo attribute in the AssemblyInfo.cs for WP7. So I did:
[assembly: InternalsVisibleTo("Cirrious.MvvmCross.WindowsPhone")]
But this doesn't make any difference. I use the following code to send two variables form my BeckhoffViewModel to my BeckhoffSensorViewModel.
BeckhoffViewModel:
public IMvxCommand BeckhoffSensor1
{
get
{
return new MvxRelayCommand(kvpSens1);
}
}
private void kvpSens1()
{
RequestNavigate<BeckhoffSensorViewModel>(new { VarType = "short", Variable = ".countertest" });
}
BeckhoffSensorViewModel:
public BeckhoffSensorViewModel(string VarType, string Variable)
{
_vartype = VarType;
_variable = Variable;
}
Anything I'm overlooking? I also looked at the other stackoverflow topic mentioned in the exception but couldn't really understand it.
The anonymous class will most definitely be created as internal by the compiler - which is why you need the line [assembly: InternalsVisibleTo("Cirrious.MvvmCross.WindowsPhone")]
Can you check that the AssemblyInfo.cs file definitely being linked into the project (and that this is the project containing the ViewModel/anonymous-class code)?
If that is the case, can you check the methodAccessException to see what the message is?
If that doesn't help, can you use a tool like Reflector to check the internalVisible attribute is actually present on the core/application assembly?

NUnit extension

Hi All i have a question regarding NUnit Extension (2.5.10).
What i am trying to do is write some additional test info to the
database. For that i have created NUnit extension using Event
Listeners.
The problem i am experiencing is that public void
TestFinished(TestResult result) method is being called twice at
runtime. And my code which writes to the database is in this method
and that leaves me with duplicate entries in the database. The
question is: Is that the expected behaviour? Can i do something about
it?
The extension code is below. Thanks.
using System;
using NUnit.Core;
using NUnit.Core.Extensibility;
namespace NuinitExtension
{
[NUnitAddinAttribute(Type = ExtensionType.Core,
Name = "Database Addin",
Description = "Writes test results to the database.")]
public class MyNunitExtension : IAddin, EventListener
{
public bool Install(IExtensionHost host)
{
IExtensionPoint listeners = host.GetExtensionPoint("EventListeners");
if (listeners == null)
return false;
listeners.Install(this);
return true;
}
public void RunStarted(string name, int testCount){}
public void RunFinished(TestResult result){}
public void RunFinished(Exception exception){}
public void TestStarted(TestName testName){}
public void TestFinished(TestResult result)
{
// this is just sample data
SqlHelper.SqlConnectAndWRiteToDatabase("test", test",
2.0, DateTime.Now);
}
public void SuiteStarted(TestName testName){}
public void SuiteFinished(TestResult result){}
public void UnhandledException(Exception exception){}
public void TestOutput(TestOutput testOutput){}
}
}
I have managed to fix the issue by simply removing my extension
assembly from NUnit 2.5.10\bin\net-2.0\addins folder. At the moment
everything works as expected but i am not sure how. I thought that you
have to have the extension/addin assembly inside the addins folder.
I am running tests by opening a solution via NUnit.exe. My extension
project is part of the solution i am testing. I have also raised this issue with NUnit guys and got the following explanation:
Most likely, your addin was being loaded twice. In order to make it easier to test addins, NUnit searches each test assembly for addins to be loaded, in addition to searching the addins directory. Normally, when you are confident that your addin works, you should remove it from the test assembly and install it in the addins folder. This makes it available to all tests that are run using NUnit. OTOH, if you really only want the addin to apply for a certain project, then you can leave it in the test assembly and not install it as a permanent addin.
http://groups.google.com/group/nunit-discuss/browse_thread/thread/c9329129fd803cb2/47672f15e7cc05d1#47672f15e7cc05d1
Not sure this answer is strictly relevant but might be useful.
I was having a play around with the NUnit library recently to read NUnit tests in so they could easily be transfered over to our own in-house acceptance testing framework.
It turns out we probably wont stick with this but thought it might be useful to share my experiences figuring out how to use the NUnit code:
It is different in that it doesn't get run by the NUnit console or Gui Runner but just by our own console app.
public class NUnitTestReader
{
private TestHarness _testHarness;
public void AddTestsTo(TestHarness testHarness)
{
_testHarness = testHarness;
var package = new TestPackage(Assembly.GetExecutingAssembly().Location){AutoBinPath = true};
CoreExtensions.Host.InitializeService();
var testSuiteBuilder = new TestSuiteBuilder();
var suite = testSuiteBuilder.Build(package);
AddTestsFrom(suite);
}
private void AddTestsFrom(Test node)
{
if (!node.IsSuite)
AddTest(node);
else
{
foreach (Test test in node.Tests)
AddTestsFrom(test);
}
}
private void AddTest(Test node)
{
_testHarness.AddTest(new WrappedNUnitTest(node, TestFilter.Empty));
}
}
The above reads NUnit tests in from the current assembly wraps them up and then adds them to our inhouse test harness. I haven't included these classes but they're not really important to understanding how the NUnit code works.
The really useful bit of information here is the static to "InitialiseService" this took quite a bit of figuring out but is necessary to get the basic set of test readers loaded in NUnit. You need to be a bit careful when looking at the tests in NUnit aswell as it includes failing tests (which I assume dont work because of the number of statics involved) - so what looks like useful documentation is actually misleading.
Aside from that you can then run the tests by implementing EventListener. I was interested in getting a one to one mapping between our tests and NUnit tests so each test is run on it's own. To achieve this you just need to implement TestStarted and TestFinished to do logging:
public void TestStarted(TestName testName)
{
}
public void TestFinished(TestResult result)
{
string text;
if (result.IsFailure)
text = "Failure";
else if (result.IsError)
text = "Error";
else
return;
using (var block = CreateLogBlock(text))
{
LogFailureTo(block);
block.LogString(result.Message);
}
}
There are a couple of problems with this approach: Inherited Test base classes from other assemblies with SetUp methods that delegate to ones in the current assembly dont get called. It also has problems with TestFixtureSetup methods which are only called in NUnit when TestSuites are Run (as opposed to running test methods on their own).
These both seem to be problems with NUnit although if you dont want to construct wrapped tests individually I think you could just put in a call to suite.Run with the appropriate parameters and this will fix the latter problem