Showing posts with label unitTesting. Show all posts
Showing posts with label unitTesting. Show all posts

Monday, February 25, 2013

Run Chai based tests with PhantomJs


PhantomJs is installed at C:\Program Files (x86)\phantomjs-1.8.1-windows
then add it to the path
i had to put chai.js in the target directory of the phantom script which makes me sad, but perhaps I'll figure that out next.

at the command prompt:

C:\Projects\mine\phantomjs>phantomjs payerportal.js>phantomjs hellophantom.js
phantom.injectJs("chai.js");

var assert = chai.assert;
var pageToTest= 'http://localhost/helloworld/';
var url = pageToTest;
page.open(url, function(status) {
 try{
       assert.typeOf('test','string','test is a string');
       
      } catch(err) {console.log('Test failed:'+err);}
        
});

Monday, February 11, 2013

What did you do this weekend?


Well it's been quite a full weekend!

During the work week:

  • Learned about WebAPI's IQueryable possibilities
  • Found out they changed the ruling on Entity Framework
    • We can now select straight into POCOs instead of only anonymous types or EF types
    • Still can't find any articles, blog posts, or announcements about this change.
  • Forced EF to allow me to do queries that span linked databases.
  • Used Knockout to consume the OData (or WebApi IQueryable)
    • complete with a user friendly search form
  • Explored PhantomJs for headless browser automation and testing
  • Updated my win forms tool for scraping data from our Stash and Crucible
  • Explored some SpecFlow

What did you do?

Thursday, January 31, 2013

Mvc4 unit(?) testing of views with BDD & SpecFlow

I wanted to unit test my mvc. I had no idea what that could mean. Not my pocos or models, my Mvc. After googling what are the primary targets taken by unit testers? Controllers, almost never Views. The level of complexity behind getting a test framework given v as our view to do v.ExecuteResult() seems over the top immense. The spec flow: Feature: Register a new User In order to register a new User As member of the site So that they can log in to the site and use its features Scenario: Browse Register page When the user goes to the register user screen Then the register user view should be displayed And the view should have a username input field The MsTest class:
using System;
using System.Web.Mvc;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using MvcContrib.TestHelper;

using MvcSpecFlow.Controllers;
using MvcSpecFlow.Views.Account;

using RazorGenerator.Testing;

using TechTalk.SpecFlow;

//http://www.codeproject.com/Articles/82891/BDD-using-SpecFlow-on-ASP-NET-MVC-Application
//http://blog.davidebbo.com/2011/06/precompile-your-mvc-views-using.html
//http://blog.davidebbo.com/2011/06/unit-test-your-mvc-views-using-razor.html

namespace MvcSpecFlow.Tests
{
  [Binding]
  public class RegisterUserSteps
  {
    ActionResult result;

    AccountController controller;

    [When(@"the user goes to the register user screen")]
    public void WhenTheUserGoesToTheRegisterUserScreen()
    {
      controller = new AccountController();
      result = controller.Register();

    }

    [Then(@"the register user view should be displayed")]
    public void ThenTheRegisterUserViewShouldBeDisplayed()
    {
      Assert.IsInstanceOfType(result, typeof(ViewResult));

      var vResult = (ViewResult)result;
      Assert.AreEqual(string.Empty, vResult.ViewName);

      vResult.AssertViewRendered().ForView(string.Empty); //should follow convention not pass a special view name
      
    }

    [Then(@"the view should have a username input field")]
    public void ThenTheViewShouldHaveAUsernameInputField()
    {
      var view = new Register();
      var doc = view.RenderAsHtml();
      var username = doc.GetElementbyId("UserName");
      Assert.IsNotNull(username);
    
    }
  }
}
The requirements:
  1. Use RazorGenerator to precompile your views
  2. The view you are testing has the RazorGenerator set as the Custom Tool
  3. The view you are testing does not have the following razor: @Html.AntiForgeryToken()
  4. Your testing project has RazorGenerator.Testing installed.

Friday, June 24, 2011

Database Unit Tests - Config Transforms

I wanted to have a configuration for the other environments to run the same tests.


  1. started out adding the sit configuration to the solution and the test project.
  2. I added the following to my Db.Tests.csproj:
    1. top property group under projectguid:
      1. <ProjectConfigFileName>App.Config</ProjectConfigFileName>
    2. and just below outputType:
      1. <OutputExtension Condition="'$(OutputExtension)' == '' ">dll</OutputExtension>
    3. then in the item group with app.config:
      1. <Content Include="App.Sit.config">      <DependentUpon>app.Config</DependentUpon>    </Content>
    4. finally just before /Project tag:



<Import Condition="'$(Configuration)' == 'Sit'" Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
  <Target Condition="'$(Configuration)' == 'Sit'" Name="PostTransformAppConfig" AfterTargets="TransformWebConfig">
    <Copy Condition="Exists('$(TransformWebConfigIntermediateLocation)\transformed\App.config')" SourceFiles="$(TransformWebConfigIntermediateLocation)\transformed\App.config" DestinationFiles="$(OutputPath)\$(AssemblyName).$(OutputExtension).config" />
    <Copy Condition="Exists('$(TransformWebConfigIntermediateLocation)\transformed\App.config')" SourceFiles="$(TransformWebConfigIntermediateLocation)\transformed\App.config" DestinationFiles="$(OutputPath)\$(AssemblyName).vshost.$(OutputExtension).config" />
  </Target>
  <Target Condition="'$(Configuration)' == 'Sit'" Name="PostTransformAppConfig" AfterTargets="Build">
    <CallTarget Targets="TransformWebConfig" />
    <Copy Condition="Exists('$(TransformWebConfigIntermediateLocation)\transformed\App.config')" SourceFiles="$(TransformWebConfigIntermediateLocation)\transformed\App.config" DestinationFiles="$(OutputPath)\$(AssemblyName).$(OutputExtension).config" />
    <Copy Condition="Exists('$(TransformWebConfigIntermediateLocation)\transformed\App.config')" SourceFiles="$(TransformWebConfigIntermediateLocation)\transformed\App.config" DestinationFiles="$(OutputPath)\$(AssemblyName).vshost.$(OutputExtension).config" />
  </Target>



Here's my app.sit.config transform file:

<ExecutionContext xdt:Transform="Replace" Provider="System.Data.SqlClient" ConnectionString="Data Source=SitServer;Initial Catalog=Init1_SIT;Integrated Security=True;Pooling=False"
        CommandTimeout="30" />
    <PrivilegedContext xdt:Transform="Replace" Provider="System.Data.SqlClient" ConnectionString="Data Source=SitServer;Initial Catalog=Init1_SIT;Integrated Security=True;Pooling=False"
          CommandTimeout="30" />



Based on

Thursday, January 28, 2010

UnitTesting made easy with the power of TypeMock

I want to test the persistence layer of my code. One of the recently added requirements for the persistence layer is that it accepts a domain class that wraps around the user name to ensure consistent handling throughout the application of a username. This is because currently the decision is to strip the Windows Domain name off of a userName before using it or storing it. Should the decision be reversed, there's a central configuration alteration to make, without having to recompile the application. How nice are changes that require a simple text file to be changed?

So the call would be:

var result=repository.GetAssociate(new UserName(DependencyContainer.GetAssociate()));
Which you can't call from the persistence layer because
  • The Dependency container is defined in an assembly not referenced by the persistence layer 
  • The UserName constructor is internal to the domain assembly
So to make the method repository.GetAssociate testable, we would have to alter the OOP design of the code to make it testable in most frameworks( because there is no public constructor for UserName).

You could of course messy up your code by using dependency injection on everything that needs testing. This concern does partly fall down if you centralize the coupling between your domain and external dependencies, but remains when you try to test individual methods inside a class, or anything internal, private, or that accesses static methods(most testing frameworks can not handle mocking out static methods, constructors, or factories, as I understand it TypeMock can)

You could make your code messier and more prone to issues in dependent code by changing username to a public interface and changing the persistence layer to accept that interface, but then automatic business logic enforcement goes out the window. If an object outside of the domain assembly can not create a copy of a domain object it has no reason to create, then it's tougher to accidentally not pass things through the proper domain classes/methods.

So how do I test this method?

Wednesday, January 6, 2010

Unit testing reference

The parts of unit testing I'm trying to commit to memory but keep referring back to are as follows:
  • Good unit test properties
    • automated and repeatable
    • easy to implement
    • once written, should remain for future use
    • anyone should be able to run it
    • should run at the push of a button
    • should run quickly
  • Is it a good unit test?
    • Can I run and get results from a unit test written weeks,months, years ago?
    • Can any member of the team run and get results from unit tests written weeks,months, years ago?
    • Can I run all the unit tests I've written in no more than a few minutes?
    • Can I run all the unit tests at the push of a button?
    • Can I write a basic unit test in no more than a few minutes?
  • TDD overview:
    • Write a failing test to prove code or functionality is missing
    • Make the test pass by writing production code that meets the expectations of the test
    • Refactor your code
    • [blogger's note: I would run the tests again after the refactoring]
  • Definitions
    • Integration test
      • testing two or more dependent software modules as a group
      • If the method you are testing has external dependencies (filesystem, sql server, OS, etc..) that you are not able to provide fakes for then it is an integration test
    • Unit test
      • a piece of code (usually a method) that runs another piece of code (usually a single method/function in isolation) and checks the correctness of some assumptions afterward. If the assumptions are wrong, the unit test is failed.
    • SUT - system under test (sometimes CUT - class under test)
      • when we test something, we refer to the thing we are testing as the SUT.
    • Regression
      • a feature that used to work and now doesn't
    • Naming conventions
      • Project
        • [ProjectUnderTest].Tests
      • Classes
        • For each class, create at least one class with the name [ClassName]Tests
      • Method
        • For each method, create at least one test method with the following name:
          • [MethodName]_[StateUnderTest]_[ExpectedBehavior]
            • StateUnderTest
              • The conditions used to produce the behavior
            • ExpectedBehavior
              • What you expect the tested method to do under the specified conditions
          • example: IsValidFileName_validFile_ReturnsTrue
    • Typical test method body
      • Arrange objects, creating and setting them up as necessary
      • Act on an object
      • Assert the expected results
    • Types of unit tests
      • State based testing/state verification
        • you act on something, assert the state after acting on that something or its collaborators(dependencies)
      • Interaction testing
        • tests how an object sends input to or recieves input from other objects
        • how that object interacts with other objects
    • Stub
      • a controllable replacement for an existing dependency(or collaborator) in the system.
      • By using a stub, you can test your code without dealing with the dependency directly.
      • Can not fail a test - not asserted against
    • Mock
      • a fake object in the system that decides whether the unit test has passed or failed. It does so by verifying whether the object under test interacted as expected with the fake object. There's usually no more than one mock per test.
      • Asserted against
    • Fake
      • generic term for mock or stub
  • Things to look out for
    • Why are we doing multiple asserts in a single test? How hard would it be to separate them into separate tests
    • Complicated hand-written stubs or mocks should be overcome with a Isolation (Mock) framework

Tuesday, January 5, 2010

My first go at Unit Testing

I've picked up "The Art of Unit Testing  with examples in .net" and I'm almost halfway done reading it. It has provided a very good walkthrough of unit testing and based on what I understand from straight reading, I've implemented some tests using Visual Studio 2008 professional's built in test functionality and RhinoMocks.

       [TestMethod]
        
public void IsValidCopyDictionary_IncludingIdentifier_EqualsReflectionCount()
        {
            
var source = Rhino.Mocks.MockRepository.GenerateStub<IAmAnAssessment>();
            
var destination=Rhino.Mocks.MockRepository.GenerateStub<IAmAnAssessment>();
            
var dictionary = ModelAssessment.ActionDictionary(destination, source, true);
            
var modelProperties=typeof (ModelAssessment).GetProperties();
            
Assert.AreEqual(dictionary.Count, modelProperties.Count(), "CopyDictionary:include is invalid");
        }
        [
TestMethod]
        
public void IsValidCopyDictionary_ExcludingIdentifier_EqualsReflectionCount()
        {
            
var source = Rhino.Mocks.MockRepository.GenerateStub<IAmAnAssessment>();
            
var destination = Rhino.Mocks.MockRepository.GenerateStub<IAmAnAssessment>();
            
var dictionary = ModelAssessment.ActionDictionary(destination, source, false);
            
var modelProperties = typeof(ModelAssessment).GetProperties();
            
Assert.AreEqual(dictionary.Count, modelProperties.Count()-1,"CopyDictionary:exclude is invalid");
        }