C# calling a static method - c#

So I'm a java developer new to C# and I can't seem to get this trivial thing working. I have a Tests class which tests a method in another class. For convenience, I made these static so not to rely on any instantiation. For some reason though, my Tests class can't seem to find my Kata class.
namespace Codewars
{
public class Program
{
static void Main(string[] args)
{
}
public static string HoopCount(int n)
{
if (n >= 10)
{
return "Great, now move on to tricks";
}
else
{
return "Keep at it until you get it";
}
}
}
}
Test:
using NUnit.Framework;
namespace Codewars
{
[TestFixture]
class Tests
{
[Test]
public static void FixedTest()
{
Assert.AreEqual("Keep at it until you get it", Kata.HoopCount(6), "Should work for 6");
Assert.AreEqual("Great, now move on to tricks", Kata.HoopCount(22), "Should work for 22");
}
}
}

Your static method is declared inside Program, not Kata, so you should refer to it as Program.HoopCount(someint)

Related

Can I have two entry points in C#

Would it be possible to use two entry points in C# instead of just having the one. For example when I have this:
using System;
namespace learning
{
class cool
{
static void Main(string[] args)
{
}
}
}
Would it be possible to have another entry point such as secondary that the program executes once the main entry point has finished.
You may want to do something like this:
class Program {
public static void EntryPoint1(string[] args) {
// Code
}
public static void EntryPoint2(string[] args) {
// Code
}
public static void Main(string[] args) {
EntryPoint1(args);
EntryPoint2(args);
}
}
Just make sure to not modify args during EnteryPoint1 or if you want to, clone them like this:
class Program {
public static void EntryPoint1(string[] args) {
// Code
}
public static void EntryPoint2(string[] args) {
// Code
}
public static void Main(string[] args) {
EntryPoint1(args.Clone());
EntryPoint2(args.Clone());
}
}
In C#, you specify the entry point using the /main: compiler option.
Imagine that the code containing containing two main() methods as follow :
namespace Application {
class ClassA {
static void main () {
// Code here
}
}
class ClassB {
static void main () {
// Code here
}
}
To use ClassA.main() as your entry point, you would specify the following when compiling:
csc /main:Application.ClassA hello.cs
You can only have a single entry point, but you can write two separate methods, call the first one, and then the second one. You will achieve what you're describing.
using System;
namespace learning
{
class cool
{
static void Main(string[] args)
{
PartOne();
PartTwo();
}
void PartOne() {
// Something happens here
}
void PartTwo() {
// Something else happens here
}
}
}
Additionally (depending on how the program starts up) you can send in arguments to specify which method you want to execute (if you don't need both of them to execute). Then you can just do an "if/else" statement that will decide which method to run depending on the arguments passed into Main

How to call a class rather than a method inside a class?

so I want to make it easy to call Console.WriteLine() (from the namespace system) so I wrote:
using System;
namespace main
{
namespace easier
{
public class print
{
public print(string input)
{
Console.WriteLine(input);
}
}
}
}
But when I try to call print("Hello World); it says CS1955: Non-invocable member 'print' cannot be used like a method.
Is there a way so I don't have to do class.print("Hello World"); just print("Hello World");?
Thanks in advance!
You can use using static
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-static
using System;
using static Easier;
class Program
{
static void Main(string[] args)
{
Print("message");
}
}
public static class Easier
{
public static void Print(string value)
{
Console.WriteLine(value);
}
}

How to call a method directly in C# [duplicate]

This question already has answers here:
C# entry point function
(7 answers)
Closed 2 years ago.
I'm very new to programming, and right now I am learning how to code. Right now I am trying to create some database program, which has some kind of menu, ability to write in data, and read the data which has been already inputed. Somehow I managed to create Menu method, but I don't know, how to open in directly from method Main. Could you please help me, what to do ? I've been looking for simmilar thread, but I can't find anything helpful for me. Again, I am learning from absolute zero, so I hope you won't be very salty about it.
PS: Places where are "Hello World" section I haven't written yet. I got it there only for filing space purposes.
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApp1
{
public class Program
{
private void Main(string[] args)
{
}
private static bool Menu()
{
Console.Clear();
Console.WriteLine("Vyberte moznost:");
Console.WriteLine("1) Zapis nóveho studenta [N]");
Console.WriteLine("2) Seznam zapsanych studentu [S]");
Console.WriteLine("3) Konec [K]");
Console.Write("\r\nSelect an option: ");
var input = Console.ReadKey();
switch (input.Key)
{
case ConsoleKey.N:
NewStudent();
return true;
case ConsoleKey.S:
StudentSeznam();
return true;
case ConsoleKey.K:
return false;
default:
return true;
}
}
public static void NewStudent()
{
Console.WriteLine("Hello World.");
}
private static void StudentSeznam()
{
Console.WriteLine("Hello World.");
}
}
public class StudentList
{
Console.WriteLine("Hello World.");
}
}
As previously mentiod. Just write Menu() in the main method.
But also, you have a Console.WriteLine directly in your class StudentList. This is not valid.
public class StudentList
{
Console.WriteLine("Hello World.");
}
Put it in a constructor, method or just remove it.
Here is a little info about classes
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/classes
Your Main method must be static, otherwise the program won't start. Then you can call the Menu() method from Main():
public class Program
{
static void Main(string[] args)
{
Menu();
}

Nested TestFixture in different classes

I am trying to create a web automation that logs in and out just once. As the website is formed by different products I am required to build different sets of tests in different classes/files(Exaple: ReportsTests, AuthenticationTests, etc.) I am perfectly able to create a TestFixture which logs in and out using the OneTimeSetup and OneTimeTearDown but that happens once for every class.
What I am trying to create is a TestFixture within a TestFixure in a way that the Login and Logout happens once on the first TestFixture and the second execute the sets of tests.
So far I've got this:
Setup.cs
using NUnit.Framework;
using System;
namespace TestsSetup
{
[TestFixture]
public class TestSetup
{
[OneTimeSetUp]
public void Setup()
{
Console.WriteLine("Login in");
}
[OneTimeTearDown]
public void Teardown()
{
Console.WriteLine("Login out");
}
}
}
TestSuit.cs
using NUnit.Framework;
using NUnit.Framework.Internal;
using System;
using TestsSetup;
namespace TCISuiteSetup
{
[TestFixture]
public class CWTestSuite : TestSetup
{
[TestFixture(1)]
public class SuiteSetup
{
[OneTimeSetUp]
public void Setup()
{
Console.WriteLine("Nothing happens on this step");
}
[OneTimeTearDown]
public void Teardown()
{
Console.WriteLine("Nothing happens on this step");
}
}
}
}
Test1.cs
using NUnit.Framework;
using NUnit.Framework.Internal;
using System;
using TCISuiteSetup;
namespace TCI.Tests
{
[TestFixture(1)]
public class UserManagerTests : CWTestSuite.SuiteSetup
{
[Test]
public void Test1()
{
Console.WriteLine("Assertion");
Assert.AreEqual(1, 1);
}
[Test]
public void Test2()
{
Console.WriteLine("Assertion");
Assert.AreEqual(1, 1);
}
}
}
test2.cs
using NUnit.Framework;
using NUnit.Framework.Internal;
using System;
using TCISuiteSetup;
namespace TCI.Tests
{
[TestFixture(1)]
public class ReportTests : CWTestSuite.SuiteSetup
{
[Test]
public void Test1()
{
Console.WriteLine("Assertion");
Assert.AreEqual(1, 1);
}
[Test]
public void Test2()
{
Console.WriteLine("Assertion");
Assert.AreEqual(1, 1);
}
}
}
If I run the test like this all tests fail. If I remove the (1) from the TestFixture(1) it pass everything but it does not hit any of the [OneTimeSetup]/[OneTimeTearDown] if I change the UserManagerTests : TestSuite.SuiteSetup to UserManager : TestSetup it hits just the first [TestFixture]
Am I missing anything.
dNesting of test fixture classes has no meaning whatsoever to NUnit. For a few years we have talked about making it meaningful, but never did anything about it.
SO, in terms of test fixtures, CWTestSuite and CWTestSuite.SetUpFixture have no relationship at all. It's just as if they were defined separately, without nesting.
If you want one fixture to group fixtures, NUnit provides SetUpFixture, which is a way to define one-time setup and teardown behavior that applies across multiple classes. A SetUpFixture is defined for a particular namespace and essentially wraps all the TestFixtures defined within that namespace and subordinate namespaces.
For example, if you were to put all your TestFixtures in some common namespace, then you could add a SetUpFixture in the same namespace like this...
namespace Some.Common.Namespace
{
[SetUpFixture]
public class TestSetup
{
[OneTimeSetUp]
public void Setup()
{
Console.WriteLine("Login in");
}
[OneTimeTearDown]
public void Teardown()
{
Console.WriteLine("Login out");
}
}
public class UserManagerTests
{
[Test]
public void Test1()
{
Console.WriteLine("Assertion");
Assert.AreEqual(1, 1);
}
[Test]
public void Test2()
{
Console.WriteLine("Assertion");
Assert.AreEqual(1, 1);
}
}
public class ReportTests
{
[Test]
public void Test1()
{
Console.WriteLine("Assertion");
Assert.AreEqual(1, 1);
}
[Test]
public void Test2()
{
Console.WriteLine("Assertion");
Assert.AreEqual(1, 1);
}
}
}
Note that I have made no use of inheritance in this example. It's not required and would break things if I had used it. If you need some common initialization logic for some but not all of the fixtures in the namespace, then you can give them a common base class, but that must be separate from the SetUpFixture and should ideally be abstract.
As a minor note, I removed all redundant [TestFixture] annotations. That's the style I recommend.
I found a way but maybe it is not the most elegant:
Setup.cs
using NUnit.Framework;
using System;
namespace TestsSetup
{
[TestFixture]
public class CWTestSuite : TestSetup
{
[TestFixture]
public class SuiteSetup
{
static private bool isLoggedOn;
[OneTimeSetUp]
public void TestSuiteSetup()
{
if (isLoggedOn == false)
{
Console.WriteLine("Loggin happens here");
isLoggedOn = true;
}
}
}
}
[SetUpFixture]
public class TestSetup
{
[OneTimeTearDown]
public void Teardown()
{
Console.WriteLine("Login out happens here");
}
[TestFixture]
public class Testing
{
[Test]
public void Test1()
{
Console.WriteLine("All tests for this product has been executed");
}
}
}
}
any of the test.cs matching the following format
using NUnit.Framework;
using NUnit.Framework.Internal;
using System;
using static TestsSetup.CWTestSuite;
namespace TestSetup
{
[TestFixture]
public class UserManagerTests : SuiteSetup
{
[Test]
public void Test3()
{
Console.WriteLine("Assertion");
Assert.AreEqual(1, 1);
}
[Test]
public void Test4()
{
Console.WriteLine("Assertion");
Assert.AreEqual(1, 1);
}
}
}
I could not get rid of the [TestFixture] within the [TestFixture] (Setup.cs/public class CWTestSuite). If I delete it it will hit the [OneTimeTearDown] after running the tests in a class.
I had to add a flag on the login steps as that [OneTimeSetUp] is called at the beginning of every set of tests.
The only way I found to trigger the [OneTimeTearDown] was to add a [TestFixture]/[Test] afterwards. it is called at the very end and it may just print a console.log but it needs to be there and it needs to be called.
BTW. This is a possible solution/work around but not recommended at all. If you want to do something like this I recommend using NUnit + SpecFlow (The [BeforeTestRun] is what you are looking for.

Does conditional compilation optimise away methods that generate input arguments?

In C#, we can perform conditional compilation using #if / #endif statements or with Conditional attributes. For example, the following code will print something only for a debug build:
public static void Main(string[] args)
{
CheckResult();
}
[Conditional("DEBUG")]
private static void CheckResult()
{
System.Console.WriteLine("everything is fine");
}
What happens, though, if this CheckResult() method accepts arguments, and we use it like so?
public static void Main(string[] args)
{
CheckResult(CalculateSomethingExpensive() == 100);
}
private static int CalculateSomethingExpensive()
{
result = //some sort of expensive operation here
return result;
}
[Conditional("DEBUG")]
private static void CheckResult(bool resultIsOK)
{
System.Console.WriteLine(resultIsOK ? "OK" : "not OK");
}
In this case, what compiler rules decide whether the expensive method is executed or optimised away? For example, is it guaranteed to be removed if it makes no changes to the state of any object?
I understand that the uncertainty can be removed by explicitly using #if but when one has a large code base with hundreds of Debug.Assert() statements, this can get unsightly very quickly.
So, with a little modification, here is what is compiled (under Release):
class Program
{
public static void Main(string[] args)
{
CheckResult(CalculateSomethingExpensive() == 100);
}
private static int CalculateSomethingExpensive()
{
var result = new Random().Next(100);//some sort of expensive operation here
return result;
}
[Conditional("DEBUG")]
private static void CheckResult(bool resultIsOK)
{
System.Console.WriteLine(resultIsOK ? "OK" : "not OK");
}
}
Which is pretty much the same as your example except modified to compile. Compiling it and then running it through the decompiler, results in this:
internal class Program
{
public Program()
{
}
private static int CalculateSomethingExpensive()
{
return (new Random()).Next(100);
}
[Conditional("DEBUG")]
private static void CheckResult(bool resultIsOK)
{
Console.WriteLine((resultIsOK ? "OK" : "not OK"));
}
public static void Main(string[] args)
{
}
}
You can see that the only difference is that the CheckResult call is removed from Main. This means that the full call is removed. Even if CheckResult or CalculateSomethingExpensive had side-effects, those will be removed.
The interesting thing is that the methods are still there in the compiled output, just the calls are removed, so don't use [Conditional(Debug)] to hide secrets used during debugging.

Categories

Resources