- Some developers were advising to create one huge test with many assertions, which will start with Login (Authenticate, LogOn, StartSession etc.) method and end with Logout (CloseSession, LogOff, etc). This idea is OK, but it is NOT a UNIT test.
- Other developers were advising to use some unit testing libraries that enable passing the state between test methods. This idea is also OK, but this is the way of creating integration tests, not the unit tests!
- The last idea was to log in before and log out after every operation in each unit test. This will also work, but you have to repeat a lot of code, which is a very bad habit.
It is a generic interface, which bases on type, that must by disposable. For example if you want to create session before running each test method and close it after running of each method, you can create your base type like this:
using ThirdPartySystemTests.Service; using System; namespace ThirdPartySystemTests { public class SessionFixture : IDisposable { private SessionHelper sessionHelper; public SessionHelper LogOnUser() { sessionHelper = new SessionHelper(); sessionHelper.Client = new ThirdPartySystemClient(); sessionHelper.SessionId = sessionHelper.Client.login ( sessionHelper.LOGIN, sessionHelper.PASSWORD ); return sessionHelper; } public void Dispose() { bool sessionClosed = sessionHelper.Client.endSession(sessionHelper.SessionId); } } public class SessionHelper { public ThirdPartySystemClient Client { get; set; } public string SessionId { get; set; } public string LOGIN = "User"; public string PASSWORD = "Password"; } }
This disposable type has 2 methods: first method creates session on the ThirdPartySystem and the second one closes this session on disposal of the SessionFixture object.
Now it is time to implement tests of ThirdPartySystem using xUnit test with our SessionFixture.
using ThirdPartySystemTests.Service; using System; using Xunit; namespace ThirdPartySystemTests { public class Tests : IUseFixture{ private SessionHelper sessionHelper; public void SetFixture(SessionFixture sessionFixture) { sessionHelper = sessionFixture.LogOnUser(); } [Fact] private void GetProductsListTest() { Product[] products = sessionHelper.Client.GetProductList(sessionHelper.SessionId); Assert.NotEmpty(products); } [Fact] private void GetCustomersListTest() { Customer[] customers = sessionHelper.Client.GetCustomersList(sessionHelper.SessionId); Assert.NotEmpty(customers); } [Fact] private void CreateProductTest() { Prodcut product = new Product { Name = "Laptop", Price = 1000, Quantity = 20 }; int productId = sessionHelper.Client.CreateProduct(sessionHelper.SessionId, product); Assert.True(productId > 0); } } }
Now the LogOnUser method will run before each execution of every test in the class, that implements IUseFixture
As a result, you have a independent set of unit tests, which do not have any connections and can be run separately. This solution is elegant, easy, safe and it observes the principles of unit tests.
You can also use IUseFixture to e.g. run methods from the base types, create configuration of some objects in the database, prepare data for further operations etc.
0 comments:
Post a Comment