i am asking how to run multiple test method in order that they are in same file.
For example i have this Unit Test File name
public class UniTest1
{
[TestMethod]
public void Login()
[TestMethod]
public void Logout()
[TestMethod]
public void SignIn()
[TestMethod]
public void ForgetPassword()
}
I want them in this order:
Login()
Logout()
ForgetPassword()
SignIn()
Just to clarify i want this order to check if this email already exist or not
If you structure your test cases to contain the code for the setup, action and assertions for that particular case, you do not need to run them in any particular order. A good advice would be to aim to not have any dependencies between the test cases, for instance, you should need to depend upon a "Login" test to have run prior to "LogOut". Instead the setup of the test code in the "LogOut" case would initiate the logged in session and set the stage for the "LogOut" action to happen.
If you find that multiple test cases share common setup code and teardown code, you could use the TestInitialize and TestCleanup properties on some methods, as such:
namespace UserInteractionTests
{
[TestClass]
public class UserAuthenticationTestt
{
[TestInitialize]
public void TestSetup()
{
/* Put your common initialization code here */
}
[TestMethod]
public void AnAuthorizedUserCanLogin()
{
/* put your setup, action and assertion here
from your system under test
*/
}
[TestMethod]
public void ALoggedInUserCanLogOut()
{
/* put your setup, action and assertion here
from your system under test
*/
}
[TestCleanup]
public void TestCleanup()
{
/* Put your common teardown code here.. */
}
}
}
You're setting up one big Test with multiple steps but not four dedicated tests.
Here an example:
public class UniTest1
{
[TestMethod]
public void LoginSuccess()
{
// Try to Log in
o.Login("user", "pw");
Assert.AreEqual(true, o.ImLoggedIn);
}
[TestMethod]
public void LoginWrongPw()
{
// Try to Log in
o.Login("user", "wrongpw");
Assert.AreEqual(false, o.ImLoggedIn);
}
[TestMethod]
public void LogOutSuccess()
{
// Login
o.Login("user", "pw");
// Check if steup is completed
Assert.AreEqual(true, o.ImLoggedIn);
bool ok = o.LogOut();
Assert.AreEqual(true, ok);
}
[TestMethod, ExpectedException(NotLoggedInException)]
public void LogOutNoLogout()
{
// Try to Log in
Assert.AreEqual(false, o.ImLoggedIn);
bool ok = o.LogOut();
}
}
As you can see every test is independend from the others.
If you need a logout-test you have to setup the environment for it and not "hope" that other tests to so.
Related
what I have here is my script in selenium c# using NUnit framework with multiple test as you can see below and it's connected to my TestRail and I am wondering if there is any way to check if my test is passed before the actual test is done.
[Test, Order(0)]
public void Login()
{
Navigate.ToLoginPage();
Log.In("user");
TestRailServer.Result("1"); //1 is testcase id
}
[Test, Order(1)]
public void RegisterUser()
{
Add.User();
TestRailServer.Result("2"); //2 is testcase id
}
The TestRailServer.Result("1") you see in the test is my connection in testrail it will decide if the test case in testrail is passed or failed based in the TestMethod(Login and RegisterUser)
Here's my code in TestRail connection
private static TestRailClient trClient;
public static void Result(string testCaseID)
{
ulong testRunID = "testRailID";
string testrailComment;
trClient = new TestRailClient("https://client.testrail.net/",
"username", "password");
var result = TestContext.CurrentContext.Result.Outcome.Status;
var testrailStatus = result switch
{
TestStatus.Failed => ResultStatus.Failed,
TestStatus.Passed => ResultStatus.Passed,
_ => ResultStatus.Retest
};
testrailComment = (testrailStatus == ResultStatus.Failed) ? TestContext.CurrentContext.Result.Message : "Passed";
trClient.AddResultForCase(testRunID, ulong.Parse(testCaseID), testrailStatus, testrailComment);
}
But the problem is the TestRailServer.Result is called before the test is done so I need a way to tell if my test passed before it executes the TestRailServer
Thank for the help if there is any and apology if you find it difficult to undestand
I've not used testrail, but I've used Nunit a fair amount.
My understand is that NUnit only knows if it has failed by doing an assert. If you don't have an assert in your code (and I don't see any at the level you've posted) your tests will always pass on completion. The challenge with your approach is that a failing assert will stop the test and you potentially won't get any result. That's how NUnit is designed - it's for unit tests that should take miliseconds afterall.
Instead of you ending every test line interacting with the reporter, move it to a [Teardown] method. That way the test completes (in a pass or fail state) and reporting is done after the event.
Something like:
public string testId;
[Test, Order(0)]
public void test1()
{
testId= "1";
Navigate.ToLoginPage();
Log.In("user");
//assert here
}
[Test, Order(1)]
public void test2()
{
testId= "2";
Add.User();
//assert here
}
[TearDown]
public void TearDown()
{
TestRailServer.Result(testId);
}
(and add asserts to the tests if you don't already) :-)
I have a question on running UnitTests sequentially. Unfortunately in scenario it is not an option to run them parallel or mock the database. The project is written in .NET core 3.1 and the UnitTests need to execute database operations before and after a Unittest has run.
After reading https://www.meziantou.net/mstest-v2-execute-tests-in-parallel.htm and a lot of other articles about sequential UnitTesting I came up with this (simplified):
BaseClass:
namespace XY.Test
{
[TestClass]
public class BaseTest: TimerModel
{
private static readonly DbCreator Creator = new DbCreator();
public static readonly DbConnectionManager ConnectionManager = new DbConnectionManager();
[TestInitialize]
public void BaseTestInitialize()
{
CreateTestData();
}
[TestCleanup]
public void BaseTestCleanup()
{
RemoveTestData();
}
public void CreateTestData()
{
RemoveTestData();
Creator.ExecuteSqlFromScript(ConnectionManager, #"Resources\CreateTestData.sql");
}
public void RemoveTestData()
{
Creator.ExecuteSqlFromScript(ConnectionManager, #"Resources\EmptyTestDataTables.sql");
}
}
}
TestClass:
[assembly: Parallelize(Workers = 0, Scope = ExecutionScope.ClassLevel)] //<-- Also tried out Workers = 1 and Scope = ExecutionScope.MethodLevel
namespace XY.Test.Models
{
[TestClass]
public class TerminalConfigModelTest: BaseTest
{
[TestMethod]
[DoNotParallelize]
public void TestMethod1()
{
...
}
[TestMethod]
[DoNotParallelize]
public void TestMethod2()
{
...
}
}
}
For some reason, no matter what I do, the UnitTests are being executed parallel. What do I have to change in order to have them executed sequentially?
When I execute all tests in the test class, the TestInitialize of the base class is called twice before the TestCleanup is run. This causes the CreateTestData method to fail as indexes prevent a double insert of the test data.
What I would expect:
TestInitialize1 is called
TestMethod1 is executed
TestCleanup1 is called
TestInitialize2 is called
TestMethod2 is executed
TestCleanup2 is called
...
What happens:
TestInitialize1 is called
TestMethod1 is executed
TestInitialize2 is called before TestCleanup1 is called
TestMethod2 execution fails
Am I missunderstanding the [DoNotParallelize] option?
Paralelism isn't the problem here, my tests are definitely sequential and [ClassCleanup] also screwed me over. It's just unintuitive and weird, more info here.
I wanted to use ordered tests but it seems it's a legacy functionality only in MSTest-v1 and new versions of Visual Studio don't even support it.
Best thing i can tell you now is just don't use [ClassCleanup].
Use [TestCleanup] or [AssemblyCleanup].
I have some tests that will call some external service. They have a limit on the API calls that I can call in every second so when I run all my tests, the last ones are going to fail because the limit on the API call is reached.
How can I limit number of concurrent tests/ put a delay afterwards/ make those special ones work on 1 thread?
My code is a normal test code using TestFixture like this:
[TestFixture]
public class WithExternalResource
{
SearchProfilesResponse _searchProfilesResponse;
[OneTimeSetUp]
public async Task WithNonExistingProfile()
{
_searchProfilesResponse= await WhenSearchIsCalled(GetNonExistingProfile());
}
[Test]
public void Then_A_List_Of_Profiles_Will_Be_Returned()
{
_searchProfilesResponse.Should().NotBeNull();
}
[Test]
public void Then_Returned_List_Will_Be_Empty()
{
_searchProfilesResponse.Should().BeEmpty();
}
}
You can limit your whole fixture to single thread with:
// All the tests in this assembly will use the STA by default
[assembly:Apartment(ApartmentState.STA)]
Or you can just mit certain tests to single thread with:
[TestFixture]
public class AnotherFixture
{
[Test, Apartment(ApartmentState.MTA)]
public void TestRequiringMTA()
{
// This test will run in the MTA.
}
[Test, Apartment(ApartmentState.STA)]
public void TestRequiringSTA()
{
// This test will run in the STA.
}
}
If you want to have a delay between all tests you could add a Thread.Sleep() in Setup or TearDown:
[SetUp] public void Init()
{
/* ... */
Thread.Sleep(50);
}
[TearDown] public void Cleanup()
{ /* ... */ }
Here's my Use Case
To start writing unit tests in TDD, I need to come up with classes and methods to test, e.g. ClassUnderTest.MethodUnderTest()
The nouns are: Candidate, Admin, User, Account, Credentials, Password, ResumeWidget (the system), and last but not least, SomeOtherAbstractionIDidNotThinkOf (e.g. SecurityService).
The verbs are: Login(), Logout(), Register(), CreateAccount(), RecoverPassword(), Unlock(), ResetPassword(), Lockout(), and last but not least, SomeOtherActionIDidNotThinkOf().
To make this question most simple, let's see if we can stick with Login(). Let me see if I can start a Unit Test for that method.
Would you have a Login method somewhere?
If so, what Class would you put it in? Why?
If not, what Class and Method would you use? And Why?
I give you a small hint about how to start TDD. First, think about how to design your software based on your use case.(Ex: Account class can contain login, logout and etc., methods)
[TestFixture]
public class AccountTest
{
public Account underTest;
[SetUp]
public void setUp()
{
underTest = new Account();
}
[Test]
public void TestLoginWithValidCredentials()
{
bool isValid = underTest.Login('userName', 'password');
Assert.True(isValid );
}
[Test]
public void TestLoginWithInValidCredentials()
{
bool isValid = underTest.Login('', '');
Assert.False(isValid );
}
[Test]
//Assert Expected Lockout exception here
public void TestLockoutByPassingInValidCredentialsMoreThan5Times()
{
for (int i =0; i< 5; i++)
{
bool isValid = underTest.Login('', '');
Assert.False(isValid );
}
// the system should throw an exception about lockout
underTest.Login('', '');
}
[Test]
public void TestCreateAccount()
{
//Register event can directly call this method
bool isCreated = underTest.Create(/*User Object*/);
Assert.True(isCreated );
}
[Test]
public void TestLogout()
{
bool success = underTest.Logout('userName');
Assert.True(success);
}
[Test]
public void TestReset()
{
// both Unlock and RecoverPassword event can share this method
bool success = underTest.Reset('userName');
// mock the password reset system and return the expected value like 'BSy6485TY'
Assert.AreEqual('BSy6485TY', password);
}
}
Updated: Added more test cases to help you to design your system.
I have the following:
[TestFixture]
public class SmokeTest : BaseTest
{
[Test(Description = "Should Do This")]
public void ShouldDoThis()
{
//Tests,Assertions,etc
}
[Test(Description = "Should Do That")]
public void ShouldDoThat()
{
//Tests,Assertions,etc
}
}
With BaseTest defined as:
[TestFixture]
public class BaseTest
{
[TestFixtureSetUp]
public void SetUp()
{
// set up browsers
}
[TearDown]
public void Dispose()
{
// dispose browsers
}
}
The goal is to have the selenium browsers' drivers created once per testFixture (// set up browsers), then at the end of the Fixture, torn down. Right now the browsers are being killed after the first test though, and the second test fails with some "Unable to connect to the remote server" error.
I'd like to target the first problem here - why is the TearDown method being called after the first test?
You need to use the TestFixtureTearDown attribute instead of the TearDown attribute in your base test. The TestFixtureTearDown attribute will cause the method to be run only once at the end of all of the tests in the fixture.