41
.NET Unit Test Session Prepared By: Tom Tang [email protected] Dec. 2010 (v1.0)

DotNet unit testing training

Embed Size (px)

Citation preview

Page 1: DotNet unit testing training

.NET Unit Test Session

Prepared By:Tom Tang

[email protected]

Dec. 2010 (v1.0)

Page 2: DotNet unit testing training

●Concept●Implementation●Challenge●Automation – Hudson●Professional guideline●Q & A and sharing

Page 3: DotNet unit testing training

CONCEPTAbout unit test

Page 4: DotNet unit testing training

Concept

●Why unit test?oPrevent side-effect as less as possible.o Improve code quality and stability.o Improve maintainability.oConsolidate design.oSave time from manual testing in the future.oDescribe the usage of your libraries and classes.

Page 5: DotNet unit testing training

Concept

●How unit test help our code quality?When you are doing implementation…oHow do you confirm your design “loosely-coupled” well

enough?oHow do you keep the correct behavior of the class you’re

updating?oHow do you ensure you have fixed the bug?oHow do you describe some tricky design / use case?

●Key rule: Cut off all dependency!!!1.Human interaction dependency(UI)2.Library dependency3.Sequence dependency4.Environment dependency5.Hierarchy dependencyRemember, it’s not only testing, it’s “UNIT” testing.

Page 6: DotNet unit testing training

Concept

●Cost - You must pay, then gain…oWrite code to verify code: More code, more bug.oCost much more time than real functional implementation.oMuch more code have to be maintained.

Exchange short-term effort for long-term benefit.

Page 7: DotNet unit testing training

Concept

●Mind construction:oDo not think coverage, JUST DO IT®.oTest case shall keep growing, never think approach all at one

time.o It saves the future, not save the present.oDoing unit test is never easy, so it make quality competitive.

There’s no silver bullet.

Page 8: DotNet unit testing training

IMPLEMENTATIONWhat to do? How to do?

Page 9: DotNet unit testing training

Implementation

Introduce Visual Studio built-in unit test tool:

Page 10: DotNet unit testing training

Implementation

Best practice policy:1.Every public entry must have at least 1 unit test case.2.Pair programming technique –

One implement test case, the other one implement functionality.3.TDD (Not DDT) –

Test-Driven Development – Implement test case before implement functional code.

Page 11: DotNet unit testing training

Implementation

TDD life-cycle:

Define interface(empty class)

Write test code through the

interfaceTest Failure.

Implement functional class.

Pass test case

Commit

Developer A

Developer B

Page 12: DotNet unit testing training

Implementation

Unit test running life-cycle for a class:

ClassInitialize

TestInitialize

TestMethod

TestCleanup

ClassCleanup

TestInitialize

TestMethod

TestCleanup

Page 13: DotNet unit testing training

Implementation

How to do a useful test case:

●Awful, but at least it prevents run-time exception in some case.●Better one:

Page 14: DotNet unit testing training

Implementation

How to do a useful test case:● Is this one good idea?

Better to avoid this style, keep the meaning of “unit” in mind.

Page 15: DotNet unit testing training

Implementation

How to do a useful test case:The other bad sample…Some genius developer write a perfect bug-free implementation, how come it failed to pass test case:

???

Page 16: DotNet unit testing training

Implementation

How to do a useful test case:The other bad sample…Updating test case assume there’s an existing member…After running the creating test case, the updating test case passed.

There’s a test case sequential dependency.

Once a test case can’t be executed alone, it’s NOT an unit test case.

Page 17: DotNet unit testing training

Implementation

How to do a useful test case:How to make the case better…Preparing its own precondition is every unit test case’s “Ownership”!

Page 18: DotNet unit testing training

Implementation

How to do a useful test case:How to test error handling…FunSpec: Once user try to create duplicated member, we shall throw exception to alert user.

Page 19: DotNet unit testing training

ImplementationHow to do a useful test case:How to follow up?

1.Don’t do new unit-test case by only coverage reason.2.Build new test case by JIRA Ticket.

Page 20: DotNet unit testing training

Implementation

Ticket unit test life-cycle:

Got ticket

Write test code to reproduce

the caseTest Failure.

Fix the bug.

Pass test case

Commit

QA verify

Page 21: DotNet unit testing training

Implementation

Ticket unit test life-cycle:●Example – PMO-3357

Page 22: DotNet unit testing training

Implementation

Ticket unit test life-cycle:●Example – PMO-3357

Page 23: DotNet unit testing training

Implementation

Promotion unit test demo:

Page 24: DotNet unit testing training

Implementation

Promotion unit test demo:

Page 25: DotNet unit testing training

CHALLENGETricky technique to cut-off dependency

Page 26: DotNet unit testing training

ChallengeHow to cut-off dependency?Use MVC design to separate logic and UIprivate void OnButtonClick(EventArg e) {    if (txtBox1.Text == “ABC”) {        txtAnswer.Text = “XXX”;    } else if (txtBox1.Text == “DEF”) {        txtAnswer.Text = “YYY”;    }}

Change code design like this:private void OnButtonClick(EventArg e) {    txtAnswer.Text = new Controller().GetAnswer(txtText1.Text);}// controller class can be unit tested.public class Controller {    public string GetAnswer(string input) {        if (input == “ABC”) {            return “XXX”;        } else if (input == “DEF”) {            return “YYY”;        }    }}

Page 27: DotNet unit testing training

Challenge

How to cut-off dependency?Library dependency:You want to test “ClassA”, but “ClassA” associated with “ClassB”, and you don’t want to involve “ClassB” in this test case.

public class MathTool {    public int AddNumber(int a, int b)    {        BackendService service = new BackendService(); // Dependency happen here.        return service.AddNumberWebservice(a, b);    }}public class BackendService {    public int AddNumberWebservice(int a, int b) {        HttpClient client = new HttpClient();        client.Url = "http://LiveMathTeacher.spi/AddNumber.asmx";        client.SubmitData(a, b);        int c = (int)client.GetResponseData();        return c;    }}

Page 28: DotNet unit testing training

Challenge

public class BackendService : IService {    public int AddNumberWebservice(int a, int b) {        HttpClient client = new HttpClient();        client.Url = "http://LiveMathTeacher.spi/AddNumber.asmx";        client.SubmitData(a, b);        int c = (int)client.GetResponseData();        return c;    }}public class MockService : IService {    public int AddNumberWebservice(int a, int b) {        return a + b;    }}

Page 29: DotNet unit testing training

Challenge

How to cut-off dependency?Environment Dependency:

●If your class must access environment resource, like container(IIS)…public string GetLoginUserName() {    if (CheckToken((string)Request[“token”])) // It accesses HTTP request resource    return (string)Session[“UserName”]; // It accesses IIS memory}

Encapsulate those resource into tool classes: public class SessionManager {#if(UNIT_TEST)    // Use Dictionary structure to replace Session in unit-test    public static Dictionary<string, object> Session = new Dictionary<string, object>(); #else    public static HttpSessionState Session = HttpContext.Current.Session;#endif}

Use similar class for switching:public string GetLoginUserName() {    if (CheckToken((string)RequestManager.Request[“token”]))     return (string)SessionManager.Session[“UserName”]; }

Page 30: DotNet unit testing training

Challenge

How to cut-off dependency?Hierarchy Dependency:

●If your class inherits from the other class which you don’t have source(3rd party library…etc) and the base class would access any other dependency that you can’t cut-off…

Examples:// This class inherits from System.ServiceProcess.ServiceBase, its constructor will auto access environment resource.using System.ServiceProcess;public class MyService : ServiceBase { }

// This class inherits from System.Web.UI.Page, it’s ASP.NET class and access IIS resource.using System.Web.UI;public class MyPage : Page { }

Page 31: DotNet unit testing training

Challenge

Page 32: DotNet unit testing training

AUTOMATION - HUDSONUnit test with automation

Page 33: DotNet unit testing training

Automation - hudson

Integrate unit test with Hudson:Visit this URL for sample: http://xxx.xxx.xxx/view/banana%20DEV/job/backend.UnitTest/

Page 34: DotNet unit testing training

Automation - hudson

Integrate unit test with Hudson:

Page 35: DotNet unit testing training

Automation - hudson

Integrate unit test with Hudson:

Page 36: DotNet unit testing training

PROFESSIONAL GUIDELINESample review

Page 37: DotNet unit testing training

Professional guideline

Extract the summary from the book “Pragmatic Unit Test”:

General Principles:1.Test anything that might break2.Test everything that does break3.New code is guilty until proven innocent4.Write at least as much test code as

production code5.Run local tests with each compile6.Run all tests before check-in to repository

Questions to Ask:1.If the code ran correctly, how would I know?2.How am I going to test this?3.What else can go wrong?4.Could this same kind of problem happen

anywhere else?

Page 38: DotNet unit testing training

Professional guide line

Extract the summary from the book “Pragmatic Unit Test”:

What to Test: Use Your RIGHT-BICEP1.Are the results right?2.Are all the boundary conditions CORRECT?3.Can you check inverse relationships?4.Can you cross-check results using other

means?5.Can you force error conditions to happen?6.Are performance characteristics within

bounds?

Good tests are A TRIP1.Automatic2.Thorough3.Repeatable4.Independent5.Professional

Page 39: DotNet unit testing training

Professional guide line

Extract the summary from the book “Pragmatic Unit Test”:

CORRECT Boundary Conditions1.Conformance - Does the value conform to an

expected format?2.Ordering - Is the set of values ordered or

unordered as appropriate?3.Range - Is the value within reasonable

minimum and maximum values?4.Reference - Does the code reference

anything external that isn‘t under direct control of the code itself?

5.Existence - Does the value exist? (e.g., is non-null, non-zero, present in a set, etc.)

6.Cardinality - Are there exactly enough values?7.Time (absolute and relative) - Is everything

happening in order? At the right time? In time?

Page 40: DotNet unit testing training

Q & A AND SHARINGHow to configure Strawberry

Page 41: DotNet unit testing training

THANKSThe end