问题
Using a small (currently at 150 loc, probably less than 500 when finished) C project I'm working on, I'm teaching myself test driven development. Based on some stuff I've found on the web - especially these slides by Olve Maudal, I've just been using asserts in my unit tests.
Since I'm just learning tdd, I have thus far avoided the overhead of also learning a unit testing framework such as cunit. At this point, my thinking is that the additional learning curve - even if shallow - of a framework is not worth the effort for such a small project. I'm wondering: Is this incorrect (i.e. I'd be better off learning the framework now)? At what point does learning a framework pay off?
回答1:
The break-even for learning a unit test framework is not long to reach. Two main advantages one gets with a framework over using assert() function are
- more detailed message for assertion failure: expected vs. actual value
- execution of all test cases in lieu of stopping on first failed assertion
The two of those give hints as to where the error is located.
回答2:
From my experience with learning .NET unit testing frameworks, I pretty much started with a small project which then gave me the advantage of being able apply what I'd learned to other projects later on, regardless of their size.
I guess you might be thinking what's the point, it's only a small bit of code, right now, but I think you would be doing well to get into a framework now rather then later. It's a bit like driving a car - I learned to drive when I was 17 years old, though I didn't get my own car until two years later. I could have just ignored taking lessons until I had got my car, but I passed and already had the skills to just go on and drive.
Bit of a weird analogy, but it's how I think when it comes to learning something like a framework, or library - you just never know what it will come in handy for you.
回答3:
Learn an xUnit framework - when you get onto programming larger scale commercial projects you'll find they are used extensively.
回答4:
Since I'm just learning tdd, I have thus far avoided the overhead of also learning a unit testing framework such as cunit. At this point, my thinking is that the additional learning curve - even if shallow - of a framework is not worth the effort for such a small project. I'm wondering: Is this incorrect (i.e. I'd be better off learning the framework now)? At what point does learning a framework pay off?
I agree with philippe, Jason and Paolo, but wanted to throw in yet another way of looking at it:
The so-called xUnit frameworks are a very simple and light, both as a library to download (binaries of e.g. latest JUnit or CUnit are around 200 kilobytes), and, more imporantly, conceptually.
If you're doing (or would like to do) any unit testing at all, you would definitely benefit from using a proven tool, and learning xUnit will start paying off right away. I think you may have overestimated the "overhead" involved somewhat – don't let the word "framework" scare you ;-) – you'll be up and running with xUnit in half an hour or less.
Disclaimer: Your question isn't tagged C, so I took it as language-agnostic one. I don't know if unit testing is very different on C side (compared to Java), but I doubt it. :-)
回答5:
Following is a C# .Net example where a Moq framework
is useful in a MSTest using Visual Studio.
Observe the difference between TestOld()
and MoqTest()
. Purpose of both the tests are same. But in TestOld()
, I need to write MyMemberManagerForTest
concrete implementation. Whereas in MoqTest()
, the Moq framework will do the task for me.
_mockIMemberManager = new Mock<IMemberManager>();
_mockIMemberManager.Setup(x => x.GetMember(It.IsAny<int>())).Returns(member);
Reference: How to Use Mock Library For Your Unit Testing In C#
[TestClass()]
public class TestMembershipManager
{
private LibraryCore _targetLibraryCore;
#region Old Test withou Moq
public class MyMemberManagerForTest : IMemberManager
{
public Member GetMember(int memberID)
{
Member member = new Member()
{
MemberID = 1,
FirstName = "Lijo",
MaximumBookCanBorrow = 4,
};
return member;
}
}
private IMemberManager _memberManager;
[TestMethod()]
public void TestOld()
{
_memberManager = new MyMemberManagerForTest();
_targetLibraryCore = new LibraryCore(_memberManager);
int memberID = 1;
double expected = 12;
double actual;
//TEST
actual = _targetLibraryCore.CalculateMembershipCost(memberID);
Assert.AreEqual(expected, actual);
}
#endregion
#region Test with Moq
private Mock<IMemberManager> _mockIMemberManager;
[TestMethod()]
public void MoqTest()
{
_mockIMemberManager = new Mock<IMemberManager>();
_targetLibraryCore = new LibraryCore(_mockIMemberManager.Object);
Member member = new Member()
{
MemberID = 1,
FirstName = "Lijo",
MaximumBookCanBorrow = 4,
};
_mockIMemberManager.Setup(x => x.GetMember(It.IsAny<int>())).Returns(member);
int memberID = 1;
double expected = 12;
double actual;
//TEST
actual = _targetLibraryCore.CalculateMembershipCost(memberID);
Assert.AreEqual(expected, actual);
}
#endregion
}
For this type of testing to work it is important for the code to utilize Dependency Injection
as you can see in the overloaded LibraryCore constructor
public class LibraryCore
{
private readonly IMemberManager _memberManager;
public LibraryCore(IMemberManager memberManager)
{
this._memberManager = memberManager;
}
public double CalculateMembershipCost(int memberID)
{
double membershipCost = 0;
Member member = _memberManager.GetMember(memberID);
membershipCost = 10 + member.MaximumBookCanBorrow * 0.5;
return membershipCost;
}
}
回答6:
One note: if you are following the normal pattern of red-green-refactor, then as you refactor your unit tests, the resultant code should evolve towards being a unit test framework. For instance, you shouldn't have two copies of code that does
if (expected != actual) {printf("%d != %d", actual, expected); return -1;}
That should be refactored into something like
void AssertNotEqual(int expected, int actual, char* message)
{
if (expected != actual) {printf(message, actual, expected); return -1;}
}
来源:https://stackoverflow.com/questions/2180063/when-to-use-a-unit-testing-framework-vs-just-using-asserts