I haven't find the way to make activitySource.StartActivity return non-null activity, which is different comparing to DiagnosticSource.StartActivity behavior. Is it expected? Am I'missing something obvious?
I can see docs says: "The created activity object, if it had active listeners, or null if it has no event listeners." The following test still fails, what's the correct way of initializing ActivityListener? The package I'm using is "System.Diagnostics.DiagnosticSource" Version="5.0.0".
[TestMethod]
public void Start_Not_Null_When_ActivityListener_Added_And_ShouldListenTo_Explicitly_Defined_Activity()
{
var activitySource = new ActivitySource("ActivitySourceName");
var activityListener = new ActivityListener
{
ShouldListenTo = s => true
};
ActivitySource.AddActivityListener(activityListener);
using var activity = activitySource.StartActivity($"MethodType:/Path");
Assert.IsNotNull(activity);
}
This test pass with the help from github:
[TestMethod]
public void Start_Not_Null_When_ActivityListener_Added_And_ShouldListenTo_Explicitly_Defined_Activity()
{
var activitySource = new ActivitySource("ActivitySourceName");
var activityListener = new ActivityListener
{
ShouldListenTo = s => true,
SampleUsingParentId = (ref ActivityCreationOptions<string> activityOptions) => ActivitySamplingResult.AllData,
Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivitySamplingResult.AllData
};
ActivitySource.AddActivityListener(activityListener);
using var activity = activitySource.StartActivity("MethodType:/Path");
Assert.IsNotNull(activity);
}
The answer to this is you need to include a ActivitySamplingResult that's not set to None. The default appears to be none. MaGu's answer works because they set:
Sample = (ref ActivityCreationOptions activityOptions) => ActivitySamplingResult.AllData
The documentation for the method around StartActivity says it needs a listener but this is not the complete story you need an active listener that will do something with the activity. Setting the sample to None means it's effectively not in
Related
Learning C# should this be fixed or left alone? I can't seem to find an answer that works every action in VS didn't resolve the issue answer's I found online I either didn't understand or failed as well. Why I am asking here.
`
public class AdventureService : IAdventureService
{
public Adventure GetInitialAdventure()
{
var basePath = $" {AppDomain.CurrentDomain.BaseDirectory}Adventures";
var initialAdventure = new Adventure();
if (File.Exists($"{basePath}\\initial.json"))
{
var directory = new DirectoryInfo(basePath);
var initialJsonFile = directory.GetFiles("initial.json");
using (StreamReader fi = File.OpenText(initialJsonFile[0].FullName))
{
initialAdventure = JsonConvert.DeserializeObject<Adventure>(fi.ReadToEnd());
}
}
return initialAdventure;
}
`
You need to decide what the method will do if the deserialize call returns null.
One option is for the method to return null, in which case you just need to change the return type:
public Adventure? GetInitialAdventure()
{
//Etc.
If you prefer that the method never return null, you could change the return statement so that it replaces a null with a new Adventure.
//Rest of method up here
return initialAdventure ?? new Adventure();
}
There are maybe other options as well but these are the basics.
I'm having trouble figuring out why I can't test my driver variable, it keeps coming back null with I call Start(). I basically would like to access that variable and test it.
My current test that isn't working:
[TestMethod]
public void Start_Default_IsChrome2()
{
var dummyManager = new Mock<IRemoteDriver>();
var mockDriver = new Mock<IWebDriver>();
dummyManager.Setup(x => x.CreateRemoteWebDriver(new ChromeOptions()))
.Returns(It.IsAny<RemoteWebDriver>());
var session = new SauceSession(dummyManager.Object);
//The Start() keeps returning a null object
var driver = session.Start();
var capabilities = driver.Capabilities;
capabilities.GetCapability("browserName").Should().Be("chrome");
}
Dependency to be mocked
public interface IRemoteDriver
{
IWebDriver CreateRemoteWebDriver(ChromeOptions chromeOptions);
}
Subject Under Test
public SauceSession(IRemoteDriver driverManager)
{
remoteDriverManager = driverManager;
}
public RemoteWebDriver Start()
{
sauceUserName = Environment.GetEnvironmentVariable("SAUCE_USERNAME", EnvironmentVariableTarget.User);
sauceAccessKey = Environment.GetEnvironmentVariable("SAUCE_ACCESS_KEY", EnvironmentVariableTarget.User);
sauceOptions = new Dictionary<string, object>
{
["username"] = sauceUserName,
["accessKey"] = sauceAccessKey
};
var chromeOptions = new ChromeOptions
{
BrowserVersion = "latest",
PlatformName = "Windows 10",
UseSpecCompliantProtocol = true
};
chromeOptions.AddAdditionalCapability("sauce:options", sauceOptions, true);
//This keeps returning a null
return (RemoteWebDriver)remoteDriverManager.CreateRemoteWebDriver(chromeOptions);
}
If it helps, the Concrete implementation works just fine and that test looks like this:
[TestMethod]
public void Start_Default_IsChrome()
{
var session = new SauceSession();
var driver = session.Start();
var capabilities = ((RemoteWebDriver)driver).Capabilities;
capabilities.GetCapability("browserName").Should().Be("chrome");
}
Everything else is the same except the object that I set here:
public SauceSession()
{
remoteDriverManager = new ConcreteRemoteWebDriver();
}
class ConcreteRemoteWebDriver : IRemoteDriver
{
public IWebDriver CreateRemoteWebDriver(ChromeOptions chromeOptions)
{
return new RemoteWebDriver(new Uri("https://ondemand.saucelabs.com/wd/hub"),
chromeOptions.ToCapabilities(), TimeSpan.FromSeconds(600));
}
}
Here's the RemoteWebDriver:
public class RemoteWebDriver : IWebDriver, ISearchContext, IDisposable, IJavaScriptExecutor, IFindsById, IFindsByClassName, IFindsByLinkText, IFindsByName, IFindsByTagName, IFindsByXPath, IFindsByPartialLinkText, IFindsByCssSelector, ITakesScreenshot, IHasInputDevices, IHasCapabilities, IHasWebStorage, IHasLocationContext, IHasApplicationCache, IAllowsFileDetection, IHasSessionId, IActionExecutor
You've done your setup improperly.
dummyManager.Setup(x => x.CreateRemoteWebDriver(new ChromeOptions()))
.Returns(It.IsAny<RemoteWebDriver>());
Two things here:
You're matching on precisely an instance of new ChromeOptions(). When determining which object to return, Moq will check if the arguments passed to CreateRemoteWebDriver are the same as the ones provided in the setup. It's unlikely that
new ChromeOptions
{
BrowserVersion = "latest",
PlatformName = "Windows 10",
UseSpecCompliantProtocol = true
};
and
new ChromeOptions()
will evaluate as equal, meaning that this setup won't be matched.
You probably just meant to use It.IsAny<ChromeOptions>(), like this
dummyManager.Setup(x => x.CreateRemoteWebDriver(It.IsAny<ChromeOptions>()))
The second issue is that your return value is explicitly null.
It.IsAny<T>() always returns the default value for T. The It methods are all only used for argument matching within the Setup expression. If you use them outside of a setup expression, you're just going to get the default value of the generic argument, which in this case is a null value. It's a shame that the Moq library doesn't make this improper usage a loud error message. Consequently, you'll need to provide an actual instance of RemoteWebDriver as a return value. (Or if you can decouple the implementation from a particular concrete type, you could just return something that implements IWebDriver.)
That value could be another Mock object, potentially, but it needs to be something you've either created ahead of time, or something that can be created via the Returns callback.
A correct setup might look something like:
var mockDriver = new Mock<RemoteWebDriver>();
dummyManager.Setup(x => x.CreateRemoteWebDriver(It.IsAny<ChromeOptions>()))
.Returns(mockDriver.Object); //This could throw an exception if RemoteWebDriver needs arguments.
A small caveat is that you will actually create a RemoteWebDriver instance as a result. If that has undesirable side effects (such as creating a chrome window), you will want to consider changing your strategy from using a particular concrete type to some interface or abstract class. If you did that, the setup might look something like the below:
var mockDriver = new Mock<IWebDriver>();
dummyManager.Setup(x => x.CreateRemoteWebDriver(It.IsAny<ChromeOptions>()))
.Returns(mockDriver.Object);
I have a bit of complicated situation. I must create analyzers/ code fix providers for situations such as a parameter is only assigned but never used or local variable are never used.
For the parameter situation, I'm going for the method declaration and looking at the parameter list to get all the analyzer. I'm going through assignment expressions within the method and I filter the parameters that were assigned with an helper method.
Where it gets fuzzy is I have no clue or to know when a local variable/parameter is used or not. I've gone through symbols but they can't tell me that variable used/ not used. I could try to find how many times a variable's name was mentioned inside a method by turning the method declaration syntax context in a string and look for the parameters that were assigned but that's simply such a BAD idea.
I'm really stuck and I would some help for this from anyone who had previous experience with this kind of situation.
For people who might ask, I'm mostly looking for the missing logic for the analyzer. I have no idea how the code fix provider will work. If you have an idea of what I could do, feel free to include it in your answer ! As of now, I was thinking that a local variable that's not used could be deleted from a method and the same could go for an unused parameter. I'm not sure at the moment.
UPDATE
I'm now trying to use the DataFlow API but it's not working for me at the moment. The oldest answer of this thread gave me a starting point but it's actually not working.
I came up with my own way :
private static bool IsLocalVariableBeingUsed(VariableDeclaratorSyntax variableDeclarator, SyntaxNodeAnalysisContext syntaxNode)
{
var model = syntaxNode.SemanticModel.Compilation.GetSemanticModel(variableDeclarator.SyntaxTree);
var methodBody = variableDeclarator.AncestorsAndSelf(false).OfType<MethodDeclarationSyntax>().First();
var lastMethodNode = methodBody?.ChildNodes().LastOrDefault();
if (lastMethodNode == null)
return false;
var readWrite = syntaxNode.SemanticModel.AnalyzeDataFlow(variableDeclarator, lastMethodNode);
}
But this also is not working. When using a test with NUnit :
var input = #"
class TestClass {
void TestMethod ()
{
int i;
}
}";
I get the following message when the runtime gets to either readWrite or result(from oldest answer):
System.ArgumentOutRangeException Index was out of range Must be non negative and lesser than the size of the collection"
But before that in my analyzer, when I try to validate my node to make sure it's not null and create the appropriate elements for the data flow API, there's no code break (not sure if that is the appropriate term) but at the moment I cannot progress.
You can see whether or not most variable are used (read/written) via the DataFlowAnalysis APIs. I've written an introduction to this API on my blog.
I believe in your case, you're looking for variables that are never read.
var tree = CSharpSyntaxTree.ParseText(#"
public class Sample
{
public void Foo()
{
int unused = 0;
int used = 1;
System.Console.Write(used);
}
}");
var Mscorlib = PortableExecutableReference.CreateFromAssembly(typeof(object).Assembly);
var compilation = CSharpCompilation.Create("MyCompilation",
syntaxTrees: new[] { tree }, references: new[] { Mscorlib });
var model = compilation.GetSemanticModel(tree);
var methodBody = tree.GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().Single().Body;
DataFlowAnalysis result = model.AnalyzeDataFlow(methodBody);
var variablesDeclared = result.VariablesDeclared;
var variablesRead = result.ReadInside.Union(result.ReadOutside);
var unused = variablesDeclared.Except(variablesRead);
foreach(var variable in unused)
{
Console.WriteLine(variable);
}
Building on JoshVarty's answer, to get this to work in a diagnostic, I would register a SyntaxNodeAction for all MethodDeclaration Syntax Kinds and then look inside the body for unused variables:
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(AnalyzeIt, SyntaxKind.MethodDeclaration);
}
private static void AnalyzeIt(SyntaxNodeAnalysisContext context)
{
var method = context.Node as MethodDeclarationSyntax;
var dataFlow = context.SemanticModel.AnalyzeDataFlow(method.Body);
var variablesDeclared = dataFlow.VariablesDeclared;
var variablesRead = dataFlow.ReadInside.Union(dataFlow.ReadOutside);
var unused = variablesDeclared.Except(variablesRead);
if (unused.Any())
{
foreach (var unusedVar in unused)
{
context.ReportDiagnostic(Diagnostic.Create(Rule, unusedVar.Locations.First()));
}
}
}
I was using this code, but I am getting a compiler warning that this method of creation is deprecated. As I want to remove the warning, and move to the newer version, I want to correct the code, but I can not get the CommandLineParser 1.9.7 library to work.
CommandLine.Parser OptionParser = new CommandLine.Parser(new CommandLine.ParserSettings
{
CaseSensitive = UseCaseSensitive,
IgnoreUnknownArguments = IgnoreUnknownOptions,
MutuallyExclusive = EnableMutuallyExclusive
}
);
bool Result = OptionParser.ParseArguments(Args, this);
This code works and Result would be True/False based on the parameters of the command line and options passed. However, the following warning is posted.
Warning 1 'CommandLine.Parser.Parser(CommandLine.ParserSettings)' is obsolete: 'Use constructor that accepts Action<ParserSettings>.'
The Online help shows this as an example for using the function.
new CommandLine.Parser(configuration: () => new CommandLine.ParserSettings(Console.Error))
I tried changing the code, but I am not getting the Lambda right, and am not sure how to get this to work. While the code executes, I only get the default functions, I can not seem to change the Case Sensitive, Mutually Exclusive, etc... options.
Line using the Constructor (from the inline IDE help)
bool Result = new CommandLine.Parser(configuration: (Settings) => new CommandLine.ParserSettings(UseCaseSensitive, EnableMutuallyExclusive, IgnoreUnknownOptions, null)).ParseArguments(Args, this);
Trying again with the virtual settings:
bool Result = new CommandLine.Parser(configuration: (Settings) => new CommandLine.ParserSettings
{
CaseSensitive = UseCaseSensitive,
IgnoreUnknownArguments = IgnoreUnknownOptions,
MutuallyExclusive = EnableMutuallyExclusive
}
).ParseArguments(Args, this);
The online help has not kept up with the tool, and I could use any pointers someone might have. Thanks in advance...
Looking at the source code the constructor runs that Action passed on new settings that it creates:
public Parser(Action<ParserSettings> configuration)
{
if (configuration == null) throw new ArgumentNullException("configuration");
this.settings = new ParserSettings();
configuration(this.settings);
this.settings.Consumed = true;
}
So in the Action<ParserSettings> you should set the values you want on the parameter, not create new settings (remember that an Action<T> is a prototype for a function that takes a T and does not return a value):
var parser = new CommandLine.Parser( s =>
{
s.CaseSensitive = UseCaseSensitive;
} );
NOTE: The source code I linked to does not appear to be the same version as you are using since Parser( ParserSettings ) is marked internal in the source I found, which means you wouldn't even be able to call it, and some of the ParserSettings properties do not appear in the version I found. However, I believe this answer applies to the version you have as well.
I want to be able to mock the object that is returned by SPServer.Local but I can't seem to do it in typemock. At the moment when I debug, I see that SPServer.Local returns a null object of type SPServer. Shouldn't typemock be swapping out this instance with my fake instance? Is there something I'm doing wrong? The code runs fine on the sharepoint server.
[TestInitialize]
public void Setup()
{
fakeSite = Isolate.Fake.Instance<SPSite>(Members.ReturnRecursiveFakes);
Isolate.Swap.NextInstance<SPSite>().With(fakeSite);
fakeServer = Isolate.Fake.Instance<SPServer>(Members.ReturnRecursiveFakes);
Isolate.Swap.NextInstance<SPServer>().With(fakeServer);
sharePointStorageRepository = new SharePointStorageRepository();
}
[TestMethod]
[Isolated]
public void CreateHRFolderMethodCreatesHRFolder()
{
// arrange
// some arrange logic here
// act
var actual = sharePointStorageRepository.Create();
// assert
Assert.AreEqual(expected, actual);
}
This is the bit of code that is being run:
internal static Guid GetSiteGuid(string serverRelativeUrl, string webApplicationName)
{
Guid? guid = null;
SPServer myServer = SPServer.Local;
foreach (var serviceInstance in myServer.ServiceInstances.Where(si => si.Service is SPWebService)){
var service = (SPWebService) serviceInstance.Service;
var webapp = service.WebApplications.SingleOrDefault(wa => wa.DisplayName == webApplicationName);
if (webapp != null){
var site = webapp.Sites.SingleOrDefault(wa => wa.ServerRelativeUrl == serverRelativeUrl);
if (site != null) guid = site.ID;
}
}
if (!guid.HasValue){
throw new FileNotFoundException(
String.Format(
"Cannot find Site Collection with WebApplication \"{1}\" and ServerRelativeUrl \"{2}\" running on \"{0}\"",
myServer.Address, webApplicationName, serverRelativeUrl));
}
return guid.Value;
}
Thanks all!
I don't work in SharePoint, but something I noticed: You're not actually mocking the return of SPServer.Local anywhere. I think that's the missing step. I'm also not entirely sure you need to SwapNextInstance since I don't see anywhere that is actually creating an SPServer object.
That would change your test code to:
[TestInitialize]
public void Setup()
{
// I don't see where you're using SPSite, so I assume it's in code
// not being shown; otherwise you can remove this.
fakeSite = Isolate.Fake.Instance<SPSite>(Members.ReturnRecursiveFakes);
Isolate.Swap.NextInstance<SPSite>().With(fakeSite);
fakeServer = Isolate.Fake.Instance<SPServer>(Members.ReturnRecursiveFakes);
// INSTEAD OF THIS: Isolate.Swap.NextInstance<SPServer>().With(fakeServer);
// DO THIS:
Isolate.WhenCalled(() => SPServer.Local).WillReturn(fakeServer);
sharePointStorageRepository = new SharePointStorageRepository();
}
That WhenCalled method will mean that any time anyone asks for SPServer.Local, it'll return your fake instance.
Note that I see in the code being tested that you get the ServerInstances property. I don't see any specific return values getting set up, so I assume you're controlling the rest of the stuff in the omitted "arrange" logic.