在vs2008/vs2005中对C++项目做单元测试(Unit Test)

http://www.eng.utah.edu/~cs3500/discussions/OCT29/

 

 

The goal of this discussion section is to learn how to use the unit testing framework that is provided in Visual Studio.  What we will do is write tests to track down an error in a DLL that is a simple calculator that performs basic math operations and includes a memory to use to store one value, just like a very simple calculator.  The calculator is a class; you must instantiate it and then call the various operations.  Note - I would like you to experience debugging something that you don't have the source for, so PLEASE do not go into the calculator.cpp file and look at it.  I would normally give you just the .dll and .lib files and then you couldn't do it.  But in this case, we want to show how code coverage works, so we need the source files.  SO, PLEASE DON'T PEEK!!!

  1. Here is a zip file that contains the various parts of the project.  Extract the file into a temporary location on the C: drive.  Some stuff will not work if you extract it into your network share.
  2. We first need to set up some test options.  Go into the test options: Tools->Options->Test Tools->Test Project.  Make sure that the Default test project type is Visual C++ test project.  Then look at the Visual C++ test project options and make sure that only Unit Test and About Test Projects intro file.  The rest we don't need.  Then click OK.
  3. Now we will create our test.  Right click on the solution and choose Add->New Project.  Choose Visual C++->Test->Test Project.  Choose CalculatorTest for the name and click OK.  This will create the various files for you (you may want to rename unittest1.cpp to something more reasonable like calculatortest.cpp).
  4. Now, the calculatortest.cpp file that it creates for you is a MANAGED C++ file.  Remember the GUI work that we did earlier.  You all know the differences, but as a MANAGED class, there are some things that you can't do (for example, you can't have private data that is unmanaged class instances).  You can have pointers (using *) to data.
  5. Add #includes for to the calculator.h that we'll be using.  It should be:
#include "../Calculator/Calculator.h"
  1. Now, if you compile the solution right now, you will get about a dozen errors and warnings.  The most significant one is "error C4959: cannot define unmanaged class 'Calculator' in /clr:safe because accessing its members yields unverifiable code".  That is because we are compiling safe code and we don't want it when dealing with visual C++ unmanaged code.  So, go into CalculatorTest project and change the CLR support from MSIL safe to /clr (this is under Configuration Properties->General->Common Language Runtime Support) for the unit test project.  Now, if you do a build it will succeed.
  2. Remember that you are working inside of a managed class.  So, if you need strings and what not, you need to worry about managed and STL conversions using the utilities that we have used in the past.
  3. Finally we need to set up code coverage.  Code coverage allows us to view what lines of code in our program are actually being executed when we run the tests.  This is a way to get a measure of how complete your tests are.  So, first, go into the menu under: Test->Edit Test Run Configuration->LocalTestrun...  This pops up a dialog box.  Click on Code Coverage.  Choose the modules that you want to test coverage on (in our case it is calculator.dll).  Close and say yes to save.
  4. For the projects that we are doing code coverage on, we next need to turn on the profiler.  Right click on each project and go into the properties.  Then go into Linker->Advanced->Profile and turn on profiling.  If you have previously built the system then you need to relink these projects, so right click on each one and choose build.  This will only relink them.
  5. Next, we need to make calculatorTest reference the Calculator class.  So, right click on the CalculatorTest and add a reference to Calculator.
  6. Now, examine the code in the Additional test attributes region.  First insert a declaration of Calculator* c; just before the testInitialize indication (this will be our local pointer to a Calculator object).  Uncomment out the myTestInitialize() and the [TestInitialize()] attribute and fill in code to assign to c a new Calculator().  Do the same for myTestCleanup (uncomment out the attribute and also the code) and put in code to delete c.  Make sure that you have the attribute and the code uncommented out.  Otherwise, when you run the program, it won't know to actually run these initialization routines.
  7. Now build your solution to make sure that you didn't break something.
  8. Next step is to actually write a test method.  The best thing to do is rename the default testmethod to be TestAdd.  Then add the following tests:

Assert::AreEqual(c->add(0, 0), 0);

Assert::AreEqual(c->add(0, 1), 1);

Assert::AreEqual(c->add(1, 0), 1);

Assert::AreEqual(c->add(10, 20), 30);

Assert::AreEqual(c->add(-10, 0), -10);

Assert::AreEqual(c->add(-10, -20), -30);

  1. Once you have done this, build the solution.  Now, open the test manager window (Test->Windows->Test Manager).  You should see the TestAdd test in there.  Check the box and then right click on the test and say "Run Checked Tests.  This should run the test and it should pass the test.  Note - it is possible that you won't see the test in there.  Sometimes the test manager doesn't get updated properly and you may see the OLD test in there.  We haven't found a good solution.  It seems to work sometimes and not others.  Go into the Test Manager window and right click on the tests and say "Open Test".  The click around in the tests, eventually it seems like when you go back to the Test Manager it is repaired.  We have noticed this behaviour as well when we add new tests.  It feels like some kind of synchronization bug with the test manager.
  2. Now add 3 more test methods (don't forget to put in the [TestMethod] attribute before the tests to test sub, mul, and div routines.  Notice that you can do some cutting and pasting, but you will have to edit the tests and not use the same values as some aren't relevant (like dividing by zero).
  3. The problem with this approach is that if there is an error in a particular test, all you get is the answer and the expected answer.  You then have to guess what is wrong.  One solution is to add a comment string after the two arguments to AreEqual that tells what you are testing.  This will be displayed when you have an error.  For example, as an experiment, go in and change one of the tests so it is sure to fail and produce an incorrect answer.  You can see that it may be hard to track down the failing test.
  4. The other solution is to have ONLY one Assert:: in each TestMethod.  For something as simple as this calculator class that is a pain, but it does allow you to find exactly what test is failing and maybe only run that one test instead of all of the others.  This is the true way that you should write Unit Tests.
  5. There are other types of Assert:: that you can try.  Experiment with them and find ones that seem to work well for you.
  6. The last tests that we need are two tests to test the addMem and subMem functions.  After you run some tests and you should be able to see which of the calculator operations does not work properly.  There is one that fails, try to figure it out.  The one that doesn't work is obvious.
  7. The last thing to do is see if the code coverage worked.  This can be found by doing Test->Windows->Code Coverage Results.  This opens up a window that lets you see how much of the various functions were actually called.  What is neat is that you can then click on a particular function and it takes you to highlighted code.  The blue means that the line was executed and the red means that it wasn't.  This allows you to see how much of your program was actually executed.

If needed, here is a sample solution.

Good luck.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值