Posts

Showing posts with the label Unit Testing

Best Practices for Unit Test Case Automation

Make each test orthogonal (i.e., independent) to all the others Any given behavior should be specified in one and only one test. Otherwise if you later change that behavior, you’ll have to change multiple tests Don’t make unnecessary assertions Which specific behavior are you testing? It’s counterproductive to Assert() anything that’s also asserted by another test It just increases the frequency of pointless failures without improving unit test coverage at all Have only one logical assertion per test Unit tests are a design specification of how a certain behavior should work, not a list of observations of everything the code does Test only one code unit at a time Architecture must support testing units (i.e., classes or very small groups of classes) independently, not all chained together If you can’t do this, then your architecture is limiting your work’s quality – consider using Inversion of Control Mock out all external services and state Yo

List of Code Smells

Bad Smells in Code Duplicate Code Identical or very similar code exists in more than one location Can use 'Extract Method' refactoring Long Method A method, function or procedure that has grown too large Good naming of method is a key over here Instead of comment, add method with name explaining intention of the code Look for conditional and loops expressions Large Class When a class is trying to do too much, it often shows up as too many instance variables, sometimes call as 'God' object Check if few attributes can be segregated as another component or another subclass For GUI class, you may need to move data and behavior to a separate domain object Long Parameter List A long list of parameters in a procedure or function make readability and code quality worse In object oriented programs, parameters list tend to much smaller than procedural language If possible, remove parameter(s) and let receiver invoke method(s) to get values by

Refactoring - Replace Temp with Query

Motivation:  You are using a temporary variable to hold the result of an expression. public double GetDiscountedPrice() { double basePrice = _quantity * _itemPrice; double discountFactor; if (basePrice > 1000) discountFactor = 0.95; else discountFactor = 0.98; return basePrice * discountFactor; } Refactor as: public double GetDiscountedPrice() { return BasePrice() * DiscountFactor(); } private double BasePrice() { return _quantity * _itemPrice; } private double DiscountFactor() { if (BasePrice() > 1000) return 0.95; else return 0.98; }

Refactoring - Inline Temp

Motivation:  You have a temp that is assigned to once with a simple expression, and the temp is getting in the way of other refactorings. float dvdPrice = MovieDVD.Price(); return dvdPrice; Refactor as: return MovieDVD.Price();

Refactoring - Inline Method

Motivation:  A method's body is just as clear as its name. public float GetMovieRanking(float rating, int totalVotes, int minVotesRequired, float meanVotes) { return CalculateMovieRanking(rating, totalVotes, minVotesRequired, meanVotes); } private static float CalculateMovieRanking(float rating, int totalVotes, int minVotesRequired, float meanVotes) { float movieRanking = (rating * totalVotes + minVotesRequired * meanVotes) / (totalVotes + minVotesRequired); return movieRanking; } Refactor as: public float GetMovieRanking(float rating, int totalVotes, int minVotesRequired, float meanVotes) { float movieRanking = (rating * totalVotes + minVotesRequired * meanVotes) / (totalVotes + minVotesRequired); return movieRanking; }

Refactoring - Extract Method

Motivation:  Producing methods that efficiently communicate what they do and how they do what they do. It consists of calls to well-named methods that are all at the same level of detail. public float CalculateMovieRanking(float rating, int totalVotes, int minVotesRequired, float meanVotes) { if (rating > 10 && rating < 0) throw new Exception("The rating should be in range of 0 and 10"); if (minVotesRequired < 3000) throw new Exception("Minimum votes required for the calculation is 3000"); if (totalVotes < minVotesRequired) throw new Exception("The total votes can not be less than minimum votes required"); if (meanVotes > 10 && meanVotes < 0) throw new Exception("The mean votes should be in range of 0 and 10"); float movieRanking = (rating*totalVotes + minVotesRequired*meanVotes) / (totalVotes + minVotesRequired); return movieRanking; } Ref

Refactoring - Chain Constructors

Motivation:  Chain the constructors together to minimize the duplicate code without having to resort to initialization method.  Initialization method is troublesome because only constructor can modify read only members. public class Movie { private readonly string title; private readonly string genre; private readonly string director; public Movie(string title, string genre) { this.title = title; this.genre = genre; } public Movie(string title, string genre, string director) { this.title = title; this.genre = genre; this.director = director; } } Refactor as: public class Movie { private readonly string title; private readonly string genre; private readonly string director; public Movie(string title, string genre) { this.title = title; this.genre = genre; } public Movie2(string title, string genre, string director):this(title, genre) {