0%

Almost a decade ago, a company I worked for, started using Subversion which was a great step forward coming from Visual Source Safe.

Today, the landscape is totally different, but on enterprise level not much has changed. Some of the companies use Team Foundation Server which is great if you like total integration, but it’s source control system is not that great.
Others remained with Subversion.

They might be thinking of going to Git, but most of them are afraid of the learning curve. As with all learning processes, you just have to start somewhere, just dive-in, step by step you’ll start learning Git.

Getting Started

As a fan of Chocolatey as machine package manager, just enter at command prompt

cinst git

Or download the installer for git (at the moment it’s version 1.9.4).

Checking out the repository

If your Subversion has the default trunk, branches, tags layout

git svn clone -s <repo_url> --prefix svn/

The -s switch is a shortcut for

git svn clone -T trunk --t tags --b branches <repo_url> --prefix svn/

This will checkout the trunk of the repository by default. Now suppose your repository already had a branch called Test:

> git branch -a
* master
  remotes/svn/Test
  remotes/svn/trunk

Advanced: Shallow clone

As the default approach above will crawl trough all svn revisions which can be very slow, if you are in an environment where they are using a single Svn repository with a lot of revisions for different projects, you could be looking at a few hours, days or even weeks (+ 150000 revisions). In that particular use case follow this approach:

Get first revision of directory in gigantic repository

svn log <repo_url>

The lowest/first revision number is what you are looking for, if you want full history in git on the project. If you just wanna checkout you can use the last revision number.

Checkout repository

git svn clone -s <repo_url> --prefix svn/ -r <first-revision>

This will initialize an empty git repository, now get the trunk

git svn rebase

If you would look at your branches you would see that the test branch is not there in this case !

> git branch -a
* master
  remotes/svn/trunk

To get the remote branch to appear you need to

git svn fetch

Updating your repository

git svn rebase

It will fetch latest changes from the trunk and will try to rebase your work on top of it. If any conflicting changes where made, you’ll have to merge them.

Committing your changes

git svn dcommit

Further reading

As the entire “TDD is dead” revolt is taking place, let’s not talk about the importance of tests nor about the difference between integration, unit and load tests. But instead ask ourselves the following question if we do decide to add tests to our project:

Who is the audience/stakeholder of these tests?

Who could be the audience?

  • Is it the next developer trying to make sense of this unmaintainable puddle of misery?
  • Is it the analyst clicking on the build server’s tests tab?
  • Is it you, after a two year pause, implementing a new feature?
  • Is it you, now, just making sure the implementation behaves as expected?

Given Scenario

A user must be able to log in using his username/password.

This looks like something that could have been taken from an analysis document or could be the description on the post-it on your agile board. Now suppose you are assigned with this task, how would you organize your tests?

Let’s make it as ‘fugly’ as we can:

public interface IAuthenticationService
{
  bool Authenticate(string user, string password);
}

If we start with the simplest thing we could go for a test class called AuthenticationServiceTests. But that would quickly become a big ball of mud as we start thinking about the possible tests:

  • Authenticating with a user and password returns true if user is known and password matches
  • Authenticating with an unknown user returns false
  • Authenticating with an invalid password returns false
  • Authenticating with and null or empty user throws a businessexception
  • Authenticating with an invalid password should increment the failed logon attempts counter, to make sure we can lock out users after 3 attempts
  • Authenticating with an unconfirmed registered user throws a business exception

How about this?

[TestFixture]
public class When_user_logs_on_using_username_and_password
{
  [Test]
  public void it_returns_true()
  {
  }

  [Test]
  public void it_resets_failed_logon_attempts()
  {
  }

  [Test]
  public void it_updates_last_logon()
  {
  }
}

You could debate about not following standard .net naming conventions, but this clearly specifies our requirement. But it also involves code side effects which are necessary but may have a complete different audience (ref tests 2 and 3). This could mean you may need to organize them in that way:

  • it_resets_failed_logon_attempts is related to locking out users after 3 attempts
  • it_updates_last_logon could be related to tracking we need to do
  • it_returns_true seems a little bit technical, in fact we just express that it worked or was successful, maybe it_indicates_success could be better.

Now what happens if we logon with an unknown user, mmm, this seems database oriented, if the record does not exist in the database, the user can not login. But in real life it could mean that the user just did not register on our site or forgot his logon credentials!

So you might go for this:

[TestFixture]
public class When_an_unknown_or_unregistered_user_logs_on
{
    [Test]
    public void it_indicates_failure()
    {
    }
}

I hope I trickled your mind a bit and that I got the message trough. Expressive tests are hard work but can be very useful.

Just having full code coverage and tests where you need to deep-dive into the code to find out what they are doing may not be the point of your tests.

Tests are a way to express what the code is doing or should be doing ;)

A couple of years ago i published a comparison post on NUnit vs MsTest. One of the main benefits i felt NUnit had in comparison with MsTest was the richness of the assertion library it included.

Recently i stumbled upon an assertion framework called Shouldly. And i must say i am very impressed by it. If i would ask myself the question again whether i would prefer NUnit over MsTest, my answer would be:

It doesn’t matter as long as we can include Shouldly as assertion library.

What i liked:

  • Very natural API, did not have to second guess the usage (think about Assert.AreGreater)
  • Due to clever inspection of called method or property it even changed the way i named variables in tests, because they could tell part of the story (instead of using var verify all over the place, because it would have made no difference when test failed)
  • Mature and helpful maintainer community (logged a bug, got response same day)

The Shouldly site contains sufficient info to get started. Give it a try, maybe you like it as much as I do!

More and more people are taking the ‘There is no database’ statement to it’s limit, i think it’s time to share some insights into how we could let SQLServer help us when investigating performance issues.

Initial Setup

When it comes to performance on SQLServer these are the two most important factors that have a direct impact on system performance:

  • Memory
  • IO

As we are running on a filesystem where disk fragmentation is costly and unavoidable, there are some settings to think about when creating a new database:

  • Initial Size (MB): set this both for data and log to a reasonable size. Don’t start with the defaults of 3 Mb data and 1 Mb log, but instead with about 100 Mb for data and 50 Mb on logs (depending on the recovery model), as increasing the size will impact performance and has a major impact to fragmentation on your hard drive.
  • AutoGrowth: Default is to grow 1 Mb a time, set this to a percentage or at least 1/10 of the initial size.

While running

Remember SQLServer is your friend, using Actual Query plan while executing a query can give you hints about the underlying problem. But in general if you don’t know where to start you could use built-in statistics:

Top 25 Missing indexes

SELECT
   TOP 25 dm_mid.database_id AS DatabaseID,
   dm_migs.avg_user_impact*(dm_migs.user_seeks + dm_migs.user_scans) Avg_Estimated_Impact,
   dm_migs.last_user_seek AS Last_User_Seek,
   OBJECT_NAME(dm_mid.OBJECT_ID, dm_mid.database_id) AS [TableName],
   'CREATE INDEX [IX_' + OBJECT_NAME(dm_mid.OBJECT_ID, dm_mid.database_id) + '_' + REPLACE(REPLACE(REPLACE(ISNULL(dm_mid.equality_columns, ''), ', ', '_'), '[', ''), ']', '') +
   CASE
      WHEN
         dm_mid.equality_columns IS NOT NULL
         AND dm_mid.inequality_columns IS NOT NULL
      THEN
         '_'
      ELSE
         ''
   END
   + REPLACE(REPLACE(REPLACE(ISNULL(dm_mid.inequality_columns, ''), ', ', '_'), '[', ''), ']', '') + ']' + ' ON ' + dm_mid.statement + ' (' + ISNULL (dm_mid.equality_columns, '') +
   CASE
      WHEN
         dm_mid.equality_columns IS NOT NULL
         AND dm_mid.inequality_columns IS NOT NULL
      THEN
         ','
      ELSE
         ''
   END
   + ISNULL (dm_mid.inequality_columns, '') + ')' + ISNULL (' INCLUDE (' + dm_mid.included_columns + ')', '') AS Create_Statement
FROM
   sys.dm_db_missing_index_groups dm_mig
   INNER JOIN
      sys.dm_db_missing_index_group_stats dm_migs
      ON dm_migs.group_handle = dm_mig.index_group_handle
   INNER JOIN
      sys.dm_db_missing_index_details dm_mid
      ON dm_mig.index_handle = dm_mid.index_handle
WHERE
   dm_mid.database_ID = DB_ID()
ORDER BY
   Avg_Estimated_Impact DESC

This query will output the top 25 missing indexes ordered by estimated impact, look at indexes where the avg estimated impact is above 100000 and are frequently used (Try to avoid the INCLUDE indexes at first).

If the above query does not help you in any way, it could mean that the indexes exist but have been fragmented too much.

Index Fragmentation

SELECT
   dbschemas.[name] as 'Schema',
   dbtables.[name] as 'Table',
   dbindexes.[name] as 'Index',
   indexstats.avg_fragmentation_in_percent,
   indexstats.page_count
FROM
   sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL, NULL) AS indexstats
   INNER JOIN
      sys.tables dbtables
      on dbtables.[object_id] = indexstats.[object_id]
   INNER JOIN
      sys.schemas dbschemas
      on dbtables.[schema_id] = dbschemas.[schema_id]
   INNER JOIN
      sys.indexes AS dbindexes
      ON dbindexes.[object_id] = indexstats.[object_id]
      AND indexstats.index_id = dbindexes.index_id
WHERE
   indexstats.database_id = DB_ID()
ORDER BY
   indexstats.avg_fragmentation_in_percent desc

Look for indexes that have a fragmentation level higher than 30 % and a high page count (by default on sql server the page size is 8K).

Rebuild Indexes

ALTER INDEX PK_TABLE
ON [dbo].[TABLE] REBUILD WITH (FILLFACTOR = 90 , STATISTICS_NORECOMPUTE = OFF)

FILLFACTOR?

Usually, the higher the better (max is 100), but it depends on how often the table changes and what the index contains. Two examples:

  • PK on a int identity key, use fill factor 100% as new records are always created at the bottom (normally index fragmentation on these should be low, or a lot of records have been deleted)
  • PK on a guid key, use fill factor depending on how often new records are added (start by 80% or 90%) and monitor page splits to fine tune (see query below)

Monitor Page Splits

SELECT
   Operation,
   AllocUnitName,
   COUNT(*) as NumberofIncidents
FROM
   ::fn_dblog(null, null)
WHERE
   Operation = N'LOP_DELETE_SPLIT'
GROUP BY
   Operation,
   AllocUnitName

Further reading

Usually when doing javascript, you’ll see a lot of script inside a page. For instance when we add a date picker on a text input, you could add a script block to the page and do the necessary initialization there:

<h1>Modify your settings</h1>

<form>
  <div class="control-group">
    <label class="control-label">Birthdate</label>
    <div class="controls">
      <div class="input-append">
        <input type="text" name="birthDate" id="birthDate" />
        <span class="add-on">
          <i class="icon-calendar"></i>
        </span>
      </div>
    </div>
  </div>
</form>

<script type="text/javascript">
  $(document).ready(function() {
    $("#birthDate").datepicker({
      dateFormat: "dd-mm-yy"
    });
  });
</script>

Now what if we needed to do this more then just once? Let’s change our html to a more unobtrusive way:

<input type="text" name="birthDate" id="birthDate" data-role="datepicker" />

Now just add a new javascript file to your website and include it in our html.

(function($) {
  $(document).ready(function() {
    //datepicker convention
    $(':text[data-role="datepicker"]').datepicker({
      dateFormat: "dd-mm-yy"
    });
  });
})(jQuery);

In this file we make sure we alias ‘$’ to jQuery as another plugin we use could have aliased it differently.

If you are worried about performance of the selector used here, you can always use a class in your convention.