Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I want to keep myself as short as possible:
First: I read related posts, but they didn't help a lot.
See: What is a quality real world example of TDD in action?
Or: How do you do TDD in a non-trivial application?
Or: TDD in ASP.NET MVC: where to start?
Background:
I'm not a total TDD beginner, I know the principles
I read Rob C Martin and MC Feathers and the like
TDD works fine for me in Bowling and TicTacToe Games
But I'm kind of lost when I want to to TDD in my workplace. It's not about Mocking, I kinda do know how to mock the dependecies.
It's more:
WHEN do I code WHAT?
WHERE do I begin?
And: WHEN and HOW do I implement the "database" or "file system" code. It's cool to mock it but at integration test stage I need id as real code.
Imagine this (example):
Write a program which reads a list of all customers from a database.
Related to the customer IDs it has to search data from a csv/Excel file.
Then the business logic does magic to it.
At the end the results are written to the database (different table).
I never found a TDD example for an application like that.
EDIT:
How would you as a programmer would implement this example in TDD style?
PS: I'm not talking about db-unit testing or gui unit testing.
You could start without a database entirely. Just write an interface with the most basic method to retrieve the customers
public interface ICustomerHandler
{
List<Customer> GetCustomers(int customerId);
}
Then, using your mocking framework, mock that interface while writing a test for a method that will use and refer to an implementation of the interface. Create new classes along the way as needed (Customer, for instance), this makes you think about which properties are required.
[TestMethod()]
public void CreateCustomerRelationsTest()
{
var manager = new CustomerManager(MockRepository.GenerateMock<ICustomerHandler>());
var result = manager.CreateCustomerRelations();
Assert.AreEqual(1, result.HappyCustomers);
Assert.AreEqual(0, result.UnhappyCustomers);
}
Writing this bogus test tells you what classes are needed, like a CustomerManager class which has a method CreateCustomerRelations and two properties. The method should refer to the GetCustomer method in the interface, using the instance of the mock that was being injected in the class constructor.
Do just enough to make the project build and let you run the test for the first time, which will fail as there's no logic in the method being tested. However, you are off on a great start with letting the test dictate which input your method should take, and what output it should receive and assert. Defining the test conditions first helps you in creating a good design. Soon you will have enough code written to ensure the test confirms your method is well designed and behaves the way you want it to.
Think about what behaviour you are testing, and use this to drive a single higher level test. Then as you implement this functionality use TDD to drive out the behaviour you want in the classes you need to implement this functionality.
In your example I'd start with a simple no-op situation. (I'll write it in BDD langauge but you could similarly implement this in code)
Given there are no customers in the database
When I read customers and process the related data from the csv file
Then no data should be written to the database
This sort of test will allow you to get some of the basic functionality and interfaces in place without having to implement anything in your mocks (apart from maybe checking that you are not calling the code to do the final write)
Then I'd move on to a slightly wider example
Given there are some customers in the database
But none of these customers are in the CSV file
When I read customers and process the related data from the csv file
Then no data should be written to the database
And I would keep adding incrementally and adjusting the classes needed to do this, initially probably using mocks but eventually working up to using the real database interactions.
I'd be wary of writing a test for every class though. This can make your tests brittle and they can need changing every time you make a small refactoring like change. focus on the behaviour, not the implementation
your flow should be something like this:
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I am rewriting a C# .NET project and currently planning how I am going to do the testing.
After everything I have read I will install the XUnit framework (for the first time -- I am more experienced with MSTest). Now I am wondering whether I should combine it with FluentAssertions (which I also never used before) or rather write pure XUnit tests.
At a first glance, FluentAssertions sounds nerdy and stylish, but I'm not sure if it really will lead me to write best-readable code and how well it will scale over complex tests.
Hence I am searching for your experience and arguments. [When] (do | would) you use FluentAssertions? I'm curious.
Fluent is mostly about readability and convenience.
If you are going to write more than a handful of unit test I'd suggest using it.
I recently had the case where I was mapping object 'a' and 'b' onto object 'c' and I wanted to verify the mapper with a unit test.
So, I created an 'expectedObject' which contained all properties that object 'c' should contain once it was mapped.
As I had not written a comparer, nor did I have the need for one, it would have been very cumbersome to compare object 'c' with 'expectedObject' to assert they contain the same data. The object in question contained many properties which in turn had many properties.
But with Fluent I could simply write
c.Should().BeEquivalentTo(expectedObject);
This is much easier to read than a litany of Assert.AreEqual() and in this case, more importantly, much faster to write as well.
Fluent Assertions is a Nuget package I've been using consistently on
my projects for about 6 years. It's extremely simple to pick-up and
start using. Most people can get to grips with it within 5-10 minutes
and it will make reading your unit tests a little bit easier. Fluent
Assertions is free so there really isn't a party foul for trying it
out. I think I've introduced Fluent Assertions to over 10 teams now
and so far no one's complained. The biggest reason why most teams
don't use it is just lack of exposure to it. Using a standard approach
a unit test may look similar to this:
[TestMethod]
public void Example_test()
{
var actual = PerformLogic();
var expected = true;
Assert.AreEqual(expected, actual);
}
There's nothing wrong with this test but you need to spend a second or
two to understand what's going on. Instead, using FLuent Assertations
you can write the same test like this:
[TestMethod]
public void Example_test()
{
var result = PerformLogic();
result.Should().BeTrue();
}
Hopefully, you can see that the second example takes a lot less time
to read, as it reads like a sentence rather than an Assert statement.
Fundamentally, this is all Fluent Assertions is, a number of extension
methods that make it easier to read your unit tests compared to Assert
statements. I'm hoping you can understand why it's so easy to pick up.
All you need to do is get the outcome of your test in a result
variable, use the Should() exertion and then use Fluent Assertions
other extensions to test for your use case. Simple!
http://www.jondjones.com/c-sharp-bootcamp/tdd/fluent-assertions/what-is-fluent-assertions-and-should-i-be-using-it
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I'm new to TDD and ATDD, and I'm seeking to understand the connection between a user story and its acceptance criteria. For context, I'm building a 3-tier application in C#, with an MVC front-end.
Say, for instance, that I have the following user story:
In order to ensure Capacity Data is entered correctly
As a person updating this data
I want feedback when the data entered doesn't conform to our business rules.
It makes sense to me to break this down and define what "Capacity Data" is, and the business rules that govern this.
For instance, maybe it has a "Number of Machines" property that has to be greater than zero.
What I want to avoid doing is testing the framework--and if I follow correctly, what I want to do is test that this business logic is correctly implemented, i.e. that:
Business rules ("Number of machines must be greater than zero", and others) are correctly implemented in the codebase.
If a business rule is violated, the user is alerted of this mistake.
I believe I could test rule #2 by validating that invalid model state in the controller redirects to the same page, for instance--and there's TONS of examples of that.
However, doesn't doing this require putting decorations on the viewmodel--and that ultimately this implements the business rule from the perspective of the user? (thus satisfying #1?)
Let's say I have the following sort-of statement/unit-test:
[Test]
public void GivenCapacityModelWhenNumMachinesZeroOrLessThenModelShouldBeInvalid()
{
// Given
IValidatorThing validator = new ValidatorThing(); //What enforces the rule? Should this be a controller service? Or a decorator such as [Range(0.000001,1000000)]? Doesn't each require different testing methods?
var invalidModel = new CapacityModel(); // Or the viewmodel?
double zeroValue = 0.000001;
invalidModel.NumMachines = zeroValue;
// When
var modelIsValid = ValidatorThing.validateModel(invalidModel);
// Then
Assert.IsFalse(modelIsValid);
}
The above won't compile, of course. I've left out any particular mocking or fixturing framework out for now, to keep it simple. So, to make this test at least compile (but still fail), I have some decisions to make:
Is CapacityModel supposed to be a viewmodel? Or a DTO from the service layer? Or a metadata class in the DAL layer? I can implement either and make the test pass...but what should I really be testing?
Is the "validator" checking the behavior of a service that validates this model property? Or data annotations on the CapacityModel? Again, what should I really be testing in the context of a 3-tier application?
Some things to consider:
One thing I will know is that the database tables will have constraints that describe these rules--so it would seem that the purpose of this rule is really to communicate these rules to whoever is using the application. In that case, could I safely assume it would violate DRY to have have the rules appear in three places: the viewmodel, data entity, and database tables.
The reason we have these rules in the database is because we want to ensure if a DBA needs to mess with the records that the rules aren't accidentally violated. However, to my knowledge there isn't a great way to translate those CONSTRAINT rules up to the DAL of the application...so I suppose they would need to be repeated at least one more time in the application for sake of communicating them to the user.
So, if I were to write a unit test to fulfill the business rule wouldn't I be writing only to ensure the rules mirror the database? And separately, also writing a unit test that ensures the correct message is displayed to the user?
Any guidance you can offer would be wonderful. I want to feel that the decisions I've made were reasonable, or at least have an idea of alternative ways to solve the problem better.
Thanks,
Lawrence
EDIT:
So, ultimately I was trying to drive at a centralized way of managing validation in the application so that I could have separation of concerns--i.e., that the controller only cared about routing, the viewmodels only cared about displaying data, validators only cared about validation, etc...as opposed to having validation in the viewmodel, for instance.
I found a very helpful article that helped me to grasp how to do this, using the existing MVC infrastructure. Hopefully this will help others looking into these types of scenarios.
I suspect you may be blurring the boundary between unit tests and acceptance tests.
An acceptance test is something that is very business user focused. It treats the application as a black box but checks to confirm that the interface to the application behaves in the way the user would expect it to.
In your example I would see an acceptance test as something like:
For a simple business rule (number of machines must be greater than zero), ensure that correct feedback is given to the user in the event of the business rule being violated.
I would have a chat with the Product Owner at this stage to understand what they regard as 'correct feedback' and how they want it to be displayed.
The important thing here is that you are not testing how business rules are evaluated or what the internal mechanism is for handling errors. You are purely focused on the end-user interaction.
Of course you will also want to implement unit testing to ensure that your technical solution is solid and this is where you go in to details about where business logic is implemented.
How you handle business logic is very much a design decision. Personally, if I had the business logic in the database I would also have a table containing rule descriptions that would be used as a look-up in the event of a rule being violated. The other layers of the application would know nothing of the business logic, but would know how to pass through the error message.
I have the following method wherein the business layer is interacting with the data access layer and returning the collection object. I'm new to unit testing, but need to add automated unit tests to the solution. I read multiple articles and theory related to unit testing, but I'm confused with how to proceed. It would be really helpful If somebody can guide me with approach,
[DataObjectMethod(DataObjectMethodType.Select, true)]
public static WorkQueueBE GetItemByDetailsID(int detailsID)
{ return WorkQueueDB.GetItemByDetailsID(detailsID); }
This method gives call to GetItemsByDetailsID method in db layer, which in turn calls a stored procedure, gets the data from database, fills the collection and returns an object.
I'm gonna summarize the comments a bit as well as add some new thoughts. You write
This method gives call to GetItemsByDetailsID method in db layer,
which in turn calls a stored procedure, gets the data from database,
fills the collection and returns an object.
A comment to this is -> A unit test should only test an isolated part of your logic, that will say a single method. Not the entire flow, that's an integration test.
From what I see in your code snippet you use concrete classes. If you really want to make your application easy to test you need to use interfaces and abstract classes that can be instantiated to concrete classes as well as easily mocked and stubbed. An natural way on how to learn how to implement interfaces, abstract classes and concrete classes is to do Test Driven Development. Start with a small project and learn from there :)
If I would want to unit test your method that you've provided I would separate your logic from the data-access layer. This I would do by making the data-access layer classes implement interfaces of what they should do. This way I can mock the data-access layer and just return a specific snippet of data, just the part I need to create my unit tests for the business-layer method. After all, in this case I want to test the business-layer-method's logic, not the data-access-layer-method's.
It is quite tough to start doing unit-testing-friendly code but when you start getting a grip of you are gonna love it :)
This was a lot of theory and no concrete example because I think you need to start with a small project of your own and do it the TDD way, by doing this you will understand how everything works concerning unit testing.
Some links to get you started
https://msdn.microsoft.com/en-us/library/aa730844(v=vs.80).aspx
https://msdn.microsoft.com/en-us/library/ff847525(v=vs.100).aspx
http://www.codeproject.com/Articles/321154/Test-Driven-Development-TDD-in-Csharp
Also Pluralsight has some courses on this. Hope this helps!
I am working on writing a tool which
- sets up a connection to Sql and runs a series of stored procedures
- Hits the file system to verify and also delete files
- Talks to other subsystems through exposed APIs
I am new to the concept of TDD but have been doing a lot of reading on it. I wanted apply TDD for this development but I am stuck. There are a lot of interactions with external systems which need to be mocked/stubbed or faked. What I am finding difficult is the proper approach to take in doing this in TDD.. here is a sample of what I would like accomplished.
public class MyConfigurator
{
public static void Start()
{
CheckSystemIsLicenced(); // will throw if its not licenced. Makes call to a library owned by company
CleanUpFiles(); // clean up several directories
CheckConnectionToSql(); //ensure connection to sql can be made
ConfigureSystemToolsOnDatabase(); //runs a set of stored procedure. Range of checks are also implemented and will throw if something goes wrong.
}
}
After this I have another class which cleans up the system if things have gone wrong. For the purpose of this question, its not that relevant but it essentially will just clear certain tables and fix up database so that the tool can run again from scratch to do its configuration tasks.
It almost appears to be here that when using TDD the only tests I end up having are things like (assuming I am using FakeItEasy)
A.CallTo(()=>fakeLicenceChecker.CheckSystemIsLicenced("lickey")).MustHaveHappened();
It just is a whole lot of tests which just appear to be "MustHaveHappened". Am I doing something wrong? Is there a different way to start this project using TDD? Or is this a particular scenario where perhaps TDD is not really recommended? Any guidance would be greatly appreciated.
In your example, if the arrangement of the unit test shows lickey as the input, then it is reasonable to assert that the endpoint has been called with the proper value. In more complex scenarios, the input-to-assert flow covers more subsystems so that the test itself doesn't seem as trivial. You might set up an ID value as input and test that down the line you are outputting a value for an object that is deterministically related to the input ID.
One aspect of TDD is that the code changes while the tests do not - except for functionally equivalent refactoring. So your first tests would naturally arrange and assert data at the outermost endpoints. You would start with a test that writes a real file to the filesystem, calls your code, and then checks to see that the file is deleted as expected. Of course, the file system is a messy workspace for portable testing, so you might decide early on to abstract the file system by one step. Ditto with the database by using EF and mocking your DbContext or by using a mocked repository pattern. These abstractions can be pre-TDD application architecture decisions.
Something I do frequently is to use utility code that starts with an IFileSystem interface that declares methods that mimic a lot of what is available in System.IO.File. In production I use an implementation of IFileSystem that just passes through to File.XXX() methods. Then you can mock up and verify the interface instead of trying to setup and cleanup real files.
In this particular method the only thing you can test is that the methods were called. It's ok to do what you are doing by asserting the mock classes. It's up to you to determine if this particular test is valuable or not. TDD assumes tests for everything, but I find it to be more practical to focus your testing on scenarios where it adds value. Hard for others to make that determination, but you should trust yourself to make the call in each specific scenario.
I think integration tests would add the most bang for buck. Use the real DB and FileSystem.
If you have complex logic in the tool, then you may want to restructure the tool design to abstract out the DB and fileSystem and write the unit tests with mocks. From the code snippet you posted, it looks like a simple script to me.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
We have recently adopted the specification patterns for validating domain objects and now want to introduce unit testing of our domain objects to improve code quality.
One problem I have found is how best to unit test the validate functionality shown in the example below. The specification hits the database so I want to be able to mock it but as it is instantiated in-line I can't do this. I could work off interfaces but this increases the complexity of the code and as we may have a lot of specifications we will ultimately have a lot of interfaces (remember we are introducing unit testing and don't want to give anyone an excuse to shoot it down).
Given this scenario how would we best solve the problem of unit testing the specification pattern in our domain objects?
...
public void Validate()
{
if(DuplicateUsername())
{ throw new ValidationException(); }
}
public bool DuplicateUsername()
{
var spec = new DuplicateUsernameSpecification();
return spec.IsSatisfiedBy(this);
}
A more gentle introduction of Seams into the application could be achieved by making core methods virtual. This means that you would be able to use the Extract and Override technique for unit testing.
In greenfield development I find this technique suboptimal because there are better alternatives available, but it's a good way to retrofit testability to already existing code.
As an example, you write that your Specification hits the database. Within that implementaiton, you could extract that part of the specification to a Factory Method that you can then override in your unit tests.
In general, the book Working Effectively with Legacy Code provides much valuable guidance on how to make code testable.
If you dont want to do constructor injection of a factory, and make the specs mockable... Have you considered TypeMock? It is very powerful for dealing with this sort of thing. You can tell it to mock the next object of type X that is to be created, and it can mock anything, no virtuals etc required.
You could extract getDuplicateUsernameSpecification() into a public method of its own, then subclass and override that for your tests.
If you use IoC then you can resolve the DuplicateUsernameSpecification and in test mockup the last one
Edit: The idea is to replace direct constructor call with factory method. Something like this:
public bool DuplicateUsername()
{
var spec = MyIocContainer.Resolve<DuplicateUsernameSpecification>();
return spec.IsSatisfiedBy(this);
}