DSE6 + .NET v?

Project Repo: Interoperability Black Box

First steps. Let’s get .NET installed and setup. I’m running Ubuntu 18.04 for this setup and start of project. To install .NET on Ubuntu one needs to go through a multi-command process of keys and some other stuff, fortunately Microsoft’s teams have made this almost easy by providing the commands for the various Linux distributions here. The commands I ran are as follows to get all this initial setup done.

wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.asc.gpg
sudo mv microsoft.asc.gpg /etc/apt/trusted.gpg.d/
wget -q https://packages.microsoft.com/config/ubuntu/18.04/prod.list
sudo mv prod.list /etc/apt/sources.list.d/microsoft-prod.list
sudo chown root:root /etc/apt/trusted.gpg.d/microsoft.asc.gpg
sudo chown root:root /etc/apt/sources.list.d/microsoft-prod.list

After all this I could then install the .NET SDK. It’s been so long since I actually installed .NET on anything that I wasn’t sure if I just needed the runtime, the SDK, or what I’d actually need. I just assumed it would be safe to install the SDK and then install the runtime too.

sudo apt-get install apt-transport-https
sudo apt-get update
sudo apt-get install dotnet-sdk-2.1

Then the runtime.

sudo apt-get install aspnetcore-runtime-2.1

logoAlright. Now with this installed, I wanted to also see if Jetbrains Rider would detect – or at least what would I have to do – to have the IDE detect that .NET is now installed. So I opened up the IDE to see what the results would be. Over the left hand side of the new solution dialog, if anything isn’t installed Rider usually will display a message that X whatever needs installed. But it looked like everything is showing up as installed, “yay for things working (at this point)!

rider-01

Next up is to get a solution started with the pertinent projects for what I want to build.

dse2

Kazam_screenshot_00001

For the next stage I created three projects.

  1. InteroperationalBlackBox – A basic class library that will be used by a console application or whatever other application or service that may need access to the specific business logic or what not.
  2. InteroperationalBlackBox.Tests – An xunit testing project for testing anything that might need some good ole’ testing.
  3. InteroperationalBlackBox.Cli – A console application (CLI) that I’ll use to interact with the class library and add capabilities going forward.

Alright, now that all the basic projects are setup in the solution, I’ll go out and see about the .NET DataStax Enterprise driver. Inside Jetbrains Rider I can right click on a particular project that I want to add or manage dependencies for. I did that and then put “dse” in the search box. The dialog pops up from the bottom of the IDE and you can add it by clicking on the bottom right plus sign in the description box to the right. Once you click the plus sign, once installed, it becomes a little red x.

dse-adding-package

Alright. Now it’s almost time to get some code working. We need ourselves a database first however. I’m going to setup a cluster in Google Cloud Platform (GCP), but feel free to use whatever cluster you’ve got. These instructions will basically be reusable across wherever you’ve got your cluster setup. I wrote up a walk through and instructions for the GCP Marketplace a few weeks ago. I used the same offering to get this example cluster up and running to use. So, now back to getting the first snippets of code working.

Let’s write a test first.

[Fact]
public void ConfirmDatabase_Connects_False()
{
    var box = new BlackBox();
    Assert.Equal(false, box.ConfirmConnection());
}

In this test, I named the class called BlackBox and am planning to have a parameterless constructor. But as things go tests are very fluid, or ought to be, and I may change it in the next iteration. I’m thinking, at least to get started, that I’ll have a method to test and confirm a connection for the CLI. I’ve named it ConfirmConnection for that purpose. Initially I’m going to test for false, but that’s primarily just to get started. Now, time to implement.

namespace InteroperabilityBlackBox
using System;
using Dse;
using Dse.Auth;

namespace InteroperabilityBlackBox
{
    public class BlackBox
    {
        public BlackBox()
        {}

        public bool ConfirmConnection()
        {
            return false;
        }
    }
}

That gives a passing test and I move forward. For more of the run through of moving from this first step to the finished code session check out this

By the end of the coding session I had a few tests.

using Xunit;

namespace InteroperabilityBlackBox.Tests
{
    public class MakingSureItWorksIntegrationTests
    {
        [Fact]
        public void ConfirmDatabase_Connects_False()
        {
            var box = new BlackBox();
            Assert.Equal(false, box.ConfirmConnection());
        }

        [Fact]
        public void ConfirmDatabase_PassedValuesConnects_True()
        {
            var box = new BlackBox("cassandra", "", "");
            Assert.Equal(false, box.ConfirmConnection());
        }

        [Fact]
        public void ConfirmDatabase_PassedValuesConnects_False()
        {
            var box = new BlackBox("cassandra", "notThePassword", "");
            Assert.Equal(false, box.ConfirmConnection());
        }
    }
}

The respective code for connecting to the database cluster, per the walk through I wrote about here, at session end looked like this.

using System;
using Dse;
using Dse.Auth;

namespace InteroperabilityBlackBox
{
    public class BlackBox : IBoxConnection
    {
        public BlackBox(string username, string password, string contactPoint)
        {
            UserName = username;
            Password = password;
            ContactPoint = contactPoint;
        }

        public BlackBox()
        {
            UserName = "ConfigValueFromSecretsVault";
            Password = "ConfigValueFromSecretsVault";
            ContactPoint = "ConfigValue";
        }

        public string ContactPoint { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }

        public bool ConfirmConnection()
        {
            IDseCluster cluster = DseCluster.Builder()
                .AddContactPoint(ContactPoint)
                .WithAuthProvider(new DsePlainTextAuthProvider(UserName, Password))
                .Build();

            try
            {
                cluster.Connect();
                return true;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                return false;
            }

        }
    }
}

With my interface providing the contract to meet.

namespace InteroperabilityBlackBox
{
    public interface IBoxConnection
    {
        string ContactPoint { get; set; }
        string UserName { get; set; }
        string Password { get; set; }
        bool ConfirmConnection();
    }
}

Conclusions & Next Steps

After I wrapped up the session two things stood out that needed fixed for the next session. I’ll be sure to add these as objectives for the next coding session at 3pm PST on Thursday.

  1. The tests really needed to more resiliently confirm the integrations that I was working to prove out. My plan at this point is to add some Docker images that would provide the development integration tests a point to work against. This would alleviate the need for something outside of the actual project in the repository to exist. Removing that fragility.
  2. The application, in its “Black Box”, should do something. For the next session we’ll write up some feature requests we’d want, or maybe someone has some suggestions of functionality they’d like to see implemented in a CLI using .NET Core working against a DataStax Enterprise Cassandra Database Cluster? Feel free to leave a comment or three about a feature, I’ll work on adding it during the next session.

Distributed Coding Prefunc: Installing QuickCheck for Great Testing

Erlang LogoA few weeks ago I kicked off this series of “Distributed Coding Prefunc: Up and Running with Erlang” and had wanted to keep up the momentum, but as life goes I had to tackle a few other things first. But now, it’s time to get back on track with some distributed computing. I intend to write tests with my samples, as I often do, I decided to take a stab at .

Before going forward, note that there is QuickCheck for Haskell and there is a QuickCheck for Erlang. Since the point of this “Distributed Coding Prefunc” is to get started coding with Erlang from zero, I’ll be talking about the Erlang version here. This version is created by John Hughes and Koen Claessen, starting the Quviq Company in 2006.

To download QuickCheck choose the version you intend to use, I’ve chosen the commercial license version from the download page.

At the command prompt, install QuickCheck by running Erlang and then run the install with these commands.

Launch Erlang:

$ erl
Erlang R15B01 (erts-5.9.1)  [smp:4:4] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.9.1  (abort with ^G)
1>

Then execute the install:

1> eqc_install:install().

If the execution of the install displays this error, you’ll need to use sudo.

Installing ["pulse-1.27.7","eqc-1.27.7","eqc_mcerlang-1.27.7"].
Failed to copy pulse-1.27.7--copy returned {error,eacces}??
** exception exit: {{error,eacces},"pulse-1.27.7"}
     in function  eqc_install:'-copy_quickcheck/3-lc$^0/1-0-'/3 (../src/eqc_install.erl, line 63)
     in call from eqc_install:install2/4 (../src/eqc_install.erl, line 44)

Kill Erlang with a ctrl+c and restart Erlang with the sudo command.

$ sudo erl

Now when you install you should see the following result or something similar. You’ll be asked to continue, select lowercase ‘y’ to continue. It may be different for some, but when I hit uppercase ‘Y’ (I suppose I got overzealous to install QuickCheck) it finished as if I’d hit no or something else.

1> eqc_install:install().
Installation program for "Quviq QuickCheck" version 1.27.7.
Installing in directory /usr/local/lib/erlang/lib.
This will delete conflicting versions of QuickCheck, namely
    []
Proceed? y
Installing ["pulse-1.27.7","eqc-1.27.7","eqc_mcerlang-1.27.7"].
Quviq QuickCheck is installed successfully.
Looking in "/Users/adronhall"...   .emacs not found
Could not find your .emacs file!
Try install("path-to-emacs-file") or install(new_emacs).
Bookmark the documentation at /usr/local/lib/erlang/lib/eqc-1.27.7/doc/index.html.
ok

You’ll note above, I don’t currently have emacs installed. The reason it looks for emacs is because QuickCheck has templates/ops mode for emacs. So if you use emacs you’re in luck. I on the other hand, don’t, so I’ll just be using this from wherever I’m using it.

In addition to the lack of emacs, another important thing to note from the message is the link to documentation. Once you get this link open it up and check out the docs. They’re broken out into easily readily topic spaces and are a good place to do initial reference checking while you’re writing up your specs.

If you have a license, it is important to note, that if you’ve used sudo with your installation you’ll need to kill your running Erlang session and start it anew without sudo. Otherwise you’ll run into issue down the road trying to use the libs (unless of course you want to go hack on your permissions manually). Once you’re ready to register the software it’s simply one command, where xxxxx is your license key.

eqc:registration("xxxxxxxxxxxx").

Alright, next time we’re on to next steps…

Urban Lean Agile Tech Breakfast Meetup, Be There This Wednesday!

Are you hard core into technology and software development like Node.js, JavaScript, Ruby, Rails, .NET, Java, Clojure and more?

Do you like the ideas behind the agile manifesto, lean startup, kanban, and thinking outside of the box?

Are you digging that ASP.NET MVC Framework or waiting for the next ALT.NET meetup?

Loving that ease of Ruby on Rails to wow your user base with ease, to implement with Sinatra those clean JavaScript & jQuery enabled UX for your clients?

Want to talk shop, eat some grub, have a beverage, and get a nerd kick start in the morning?

In that case meet us for Urban Lean Agile Tech Breakfast Meetup at Mod Pizza @ 1302 6th Avenue @ 8 am on Wednesday, August 3rd.

Windows Azure SDK Unit Testing Dilemma — F5DD Plz K Thx Bye

I’m a huge advocate for high quality code. I will admit I don’t always get to write, or am always able to write high quality code. But day in and out I make my best effort at figuring out the best way to write solid, high quality, easy to maintain, easy to read code.

Over the last year or so I’ve been working with Windows Azure (Amazon Web Services and other Cloud/Utility Platforms & Infrastructure also). One of the largest gaps that I’ve experienced when working with Windows Azure is the gross disregard for unit testing and especially unit testing in a Test Driven Development style way. The design of the SDK doesn’t make unit testing a high priority, and instead focuses mostly on what one might call F5 & Run Development.

I’ll be the first to stand up and point out why F5 Driven Development (for more on this, check out Jeff Schumacher‘s Blog Entry) is the slowest & distracting ways to build high quality code. I’d also be one to admit that F5 Development encourages poor design and development. A developer has to juggle far too many things to waste time hitting F5 every few seconds to assure that the build is running and code changes, additions, or deletions have been made correctly. If a developer disregards running the application when forced to do F5 Development the tendancy is to produce a lot of code, most likely not refactored or tested, during each run of the application. The list of reasons to not develop this way can get long pretty quick. A developer needs to be able to write a test, implement the code, and run the test without a framework launching the development fabric, or worse being forced to not write a test and running code that launches a whole development fabric framework.

Now don’t get me wrong, the development fabric is freaking AWESOME!! It is one of the things that really sets Windows Azure apart from other platforms and infrastructure models that one can develop to. But the level of work and effort makes effectively, cleanly, and intelligently unit testing code against Windows Azure with the development fabric almost impossible.

But with that context, I’m on a search to find some effective ways, with the current SDK limitations and frustrations, to write unit tests and encourage test driven design (TDD) or behaviour driven design (BDD) against Windows Azure, preferably using the SDK.

So far I’ve found the following methods of doing TDD against Windows Azure.

  • Don’t use the SDK. The easiest way to go TDD or BDD against Windows Azure and not being tightly bound to the SDK & Development Fabric is to ignore the SDK altogether and use regular service calls against the Windows Azure service end points. The problem with this however, is that it basically requires one rewrite all the things that the SDK wraps (albeit with better design principles). This is very time consuming but truly gives one absolute control over what they’re writing and also releases one from the issues/nuances that the Windows Azure SDK (1.3 comes to mind) has had.
  • Abstract, abstract, and abstract with a lock of stubbing, mocking, more stubbing, and some more abstractions underneath all of that to make sure the development fabric doesn’t kick off every time the tests are run.  I don’t want to abstract something just to fake, stub, or mock it.  The level of indirection needed gets a bit absurd because of the design issues with the SDK.  The big problem with this design process to move forward with TDD and BDD is that it requires the SDK to basically be rewritten as a whole virtual stubbed, faked, and mocked layer. Reminds me of many of the reasons the Entity Framework is so difficult to work with for testing (has the EF been cleaned up, opened up, and those nasty sealed classes removed yet??)

Now I’ll admit, sometimes I miss the obvious things and maybe there is a magic “build tests real easy right here” button for Windows Azure, but I haven’t found it.  I’d love to hear what else people are doing to enable good design principles around Windows Azure’s SDK. Any thoughts, ideas, or things I ought to try would be absolutely great – I’d love to read them. Please do comment!

Test Driven Development Built Name Generator Part 3

Part 1, Part 2.

Now it is time finally for the random name generation.  I’ve gotten everything into place, so it’s just a matter of grabbing the names and randomizing among them.  Just as a check, after Part 2 was finished I had a total of 98,572 rows of data, or simply 98,572 names.

Many times I would not write actual unit tests against the database as it breaks isolation.  This time though, I’m making an exception.  First I added a reference to Generator.Core, System.Data, and System.Data.Entity.  I then created a new unit test class called DatabaseTests and added the following test to get things rolling.  Keep in mind, since these tests break isolation, I don’t write them in the red light green light idea of TDD.  My assumption is that they only prove the database is setup, running, the connection string is correct, and other minor configuration based and server based components.  In addition, yes, these are somewhat silly tests, such as the RetrieveFirstName() test has a bit of redundancy to it, but the point is to have an automated test to assure that the data has been moved into the database and is returning appropriately.

[TestClass]
public class DatabaseTests
{
    [TestMethod]
    public void RetrieveFirstFemaleName()
    {
        var entities = new GeneratorEntities();
        var returnName = (from name in entities.Names
                          where name.Type == "Female First Names"
                           select name).FirstOrDefault();
         Assert.IsNotNull(returnName);
         Assert.IsTrue(returnName.Name != string.Empty);
     }

     [TestMethod]
     public void RetrieveLastName()
     {
         var entities = new GeneratorEntities();
         var returnName = (from name in entities.Names
                           where name.Type == "Last Names"
                           select name).FirstOrDefault();
         Assert.IsNotNull(returnName);
         Assert.IsTrue(returnName.Name != string.Empty);
     }

     [TestMethod]
     public void RetrieveFirstMaleName()
     {
         var entities = new GeneratorEntities();
         var returnName = (from name in entities.Names
                           where name.Type == "Male First Names"
                           select name).FirstOrDefault();
         Assert.IsNotNull(returnName);
         Assert.IsTrue(returnName.Name != string.Empty);
     }

     [TestMethod]
     public void RetrieveFirstName()
     {
         var entities = new GeneratorEntities();
         var returnName = (from name in entities.Names
                           where name.Type == "Female First Names" || name.Type == "Male First Names"
                           select name).FirstOrDefault();
         Assert.IsNotNull(returnName);
         Assert.IsTrue(returnName.Name != string.Empty && returnName.Type == "Female First Names" ||
                       returnName.Type == "Male First Names");
    }
}

The next step now was to refactor the existing tests to prove the assembly of the name data transfer objects that would hold the first name and last name derived from the returned entity objects.

The first thing I did was break out the actual name objects into their respective files.  I did this using ReSharper, because it’s super insanely simple with ReSharper.  After that I put the class files in the project that has the model.  Next I fixed the namespaces to Generator.Core.Model.  The class files after these changes looked like the code below.

IFullName.c

namespace Generator.Core.Model
{
    public interface IFullName
    {
        string FirstName { get; set; }
        string LastName { get; set; }
    }
}

FullName.cs

namespace Generator.Core.Model
{
    public class FullName : IFullName
    {
        public FullName()
        {
            FirstName = string.Empty;
            LastName = string.Empty;
        }

         #region IFullName Members

         public string FirstName { get; set; }
         public string LastName { get; set; }

         #endregion
     }
}

NameFactory.cs

namespace Generator.Core.Model
{
    public class NameFactory
    {
        public static IFullName Build()
        {
            return new FullName {FirstName = "TestFirst", LastName = "TestLast"};
        }
    }
}

Now that we have these files moved out to the project where all the munging will happen, I’m going to start the actual refactor of the tests.  What I’ve come up with for the test refactor is as follows.

using Generator.Core.Model;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Factory.Tests
{
    [TestClass]
    public class FactoryNameBuilder
    {
        [TestMethod]
        public void VerifyFullNameObjectInstantiatesWithNames()
        {
            var name = new FullName();
            Assert.IsTrue(name.FirstName.Length == 0);
            Assert.IsTrue(name.LastName.Length == 0);
        }

        [TestMethod]
        public void VerifyFullNameObjectReturnsFromFactory()
        {
            var factory = new NameFactory();
            IFullName name = factory.Build();
            Assert.IsTrue(name.FirstName.Length > 0);
            Assert.IsTrue(name.LastName.Length > 0);
        }

        [TestMethod]
        public void VerifyFullNameIsRandom()
        {
            var factory = new NameFactory();
            IFullName nameOne = factory.Build();
            IFullName nameTwo = factory.Build();

            Assert.AreNotEqual(nameOne.FirstName, nameTwo.FirstName);
            Assert.AreNotEqual(nameOne.LastName, nameTwo.LastName);
        }
    }
}

In the factory I removed the fake return and fleshed out the appropriate build method.

using System;
using System.Collections.Generic;
using System.Linq;

namespace Generator.Core.Model
{
    public class NameFactory
    {
        public IFullName Build()
        {
            Random rand = new Random(DateTime.Now.Millisecond);

            GeneratorEntities entities = new GeneratorEntities();

            List FirstNames = (from name in entities.Names
                                      where name.Type == "Female First Names" || name.Type == "Male First Names"
                                      select name).ToList();
            List LastNames = (from name in entities.Names
                                     where name.Type == "Last Names"
                                     select name).ToList();

            FullName fullName = new FullName();
            fullName.FirstName = FirstNames[rand.Next(0, FirstNames.Count)].Name;
            fullName.LastName = LastNames[rand.Next(0, LastNames.Count)].Name;

            return fullName;
        }
    }
}

Run the tests now and you have a random name gold mine.  However, I wanted a bit more than that.  With another test added…

[TestMethod]
public void VerifyMultipleNameReturn()
{
    var factory = new NameFactory();
    List<IFullName> list = factory.Build(1000);

    for (int i = 0; i < list.Count; i++)
    {
        int compareUp = i + 1;
        if (compareUp == list.Count)
        {
            compareUp = 0;
        }
        Assert.AreNotEqual(list[compareUp].FirstName + list[compareUp].LastName, list[i].FirstName + list[i].LastName);
    }
}

…then the extra Build method.

public List<IFullName> Build(int numberOfNames)
{
    var rand = new Random(DateTime.Now.Millisecond);
    var entities = new GeneratorEntities();
 
    List<Names> FirstNames = (from name in entities.Names
                              where name.Type == "Female First Names" || name.Type == "Male First Names"
                              select name).ToList();
    List<Names> LastNames = (from name in entities.Names
                             where name.Type == "Last Names"
                             select name).ToList();

    var names = new List<IFullName>();

    for (int i = 0; i < numberOfNames; i++)
    {
        var fullName = new FullName();
        fullName.FirstName = FirstNames[rand.Next(0, FirstNames.Count)].Name;
        fullName.LastName = LastNames[rand.Next(0, LastNames.Count)].Name;
        names.Add(fullName);
    }

    return names;
}

and now I have a strong verification that I get solid randoms for 1000 name pairs.  I bumped it up to 2000 too just for fun, and didn’t hit duplicates until I put it up to 200,000.

Test Driven Development Built Name Generator Part 2

Part 1Part 3.

Alright, time to tear into getting that name data imported into the database.  To review the previous entry check out part 1.

Next I set the Windows App Project I added in part 1 to be the startup project.  After that I created a screen that looks like the image below (click to see larger image).

Also add an open file dialog control.  Next double click on the Process button and add the following code.  Make sure not to miss the instantiation of the names list property in the initialization.

using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace TextFileImporter
{
    public partial class Form1 : Form
     {
         public Form1()
         {
             InitializeComponent();
             Names = new List();
         }

         private List Names { get; set; }

         private void buttonProcessFile_Click(object sender, EventArgs e)
         {
            if (openFile.ShowDialog() == DialogResult.OK)
            {
                if (File.Exists(openFile.FileName))
                {
                    TextReader tr = new StreamReader(openFile.FileName);
                    textProcessedFile.Text = tr.ReadToEnd();
                    tr.Close();
                    // Cleanup text.
                    textProcessedFile.Text = ProcessName(textProcessedFile.Text);
                }
                else
                {
                    MessageBox.Show("Select a file that exists.", "File doesn't exist.", MessageBoxButtons.OK,
                                    MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
                }
            }
        }

        private string ProcessName(string textBody)
        {
            var regex = new Regex("[^A-Z']+");
            textBody = regex.Replace(textBody, " ");

            foreach (var s in textBody.Split(Convert.ToChar(" ")))
            {
                Names.Add(s);
            }

            return textBody;
        }
    }
}

With the beauty of those regular expressions the files will parse appropriately in about 1-5 seconds.  Next we need a way to write this data into the database.  I did this by adding a Class Project named Generator.Core and added a folder called Model.

In the Model Directory I added a new ADO.NET Entity Framework Model.  The images below show my steps through the wizard.

  • Wizard # 1 - Adding Data Model.Wizard # 1 – Adding Data Model.
  • Wizard # 2 - Adding Data Model.Wizard # 2 – Adding Data Model.
  • Wizard # 3 - Adding Data Model.Wizard # 3 – Adding Data Model.
  • Wizard # 4 - Adding Data Model.Wizard # 4 – Adding Data Model.
  • Wizard # 5 - Adding Data Model.Wizard # 5 – Adding Data Model.

.smugcontainer div {overflow: hidden;line-height: 1.1;margin-top: 10px;font-family: verdana, arial, lucida, sans-serif;font-size: 85%;background-color1: rgb(20, 20, 20);}
.smugimg li {float: left;display: block;width: 160px;height: 200px;background-position: 50% 50%;margin-right: 10px;margin-bottom: 10px;}
.smugimg li img {width: auto; height: auto; border: solid 1px #aaa; background: #555; padding: 2px; vertical-align: middle;}
.smugimg a {display: block;text-align: center;text-decoration: none; color1: rgb(240,240,240);}
.smugimg a:hover img {border: 3px solid #6da6d1; padding: 0px;}

.smugcontainer div {overflow: hidden;line-height: 1.1;margin-top: 10px;font-family: verdana, arial, lucida, sans-serif;font-size: 85%;background-color1: rgb(20, 20, 20);}
.smugimg li {float: left;display: block;width: 160px;height: 200px;background-position: 50% 50%;margin-right: 10px;margin-bottom: 10px;}
.smugimg li img {width: auto; height: auto; border: solid 1px #aaa; background: #555; padding: 2px; vertical-align: middle;}
.smugimg a {display: block;text-align: center;text-decoration: none; color1: rgb(240,240,240);}
.smugimg a:hover img {border: 3px solid #6da6d1; padding: 0px;}

At the end I also deleted the Class1.cs file from the project.

I then added a reference to the Generator.Core Project in the TextFileImporter Application Project.  Next add an application configuration file to the TextFileImporter Project with the following configuration section.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <connectionStrings>
    <add name="GeneratorEntities" connectionString="metadata=res://*/Model.Data.csdl|res://*/Model.Data.ssdl|res://*/Model.Data.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=.\carriage;Initial Catalog=Generator;Integrated Security=True;Pooling=False;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />
   </connectionStrings>
 </configuration>

At the last minute, and to make sure anyone following along with these instructions is really paying attention, I made a minor change to the database table.  I changed the column Type to a data type of nvarchar(50).  I then updated the Data.edmx file in the Generator.Core Project.  To do this open up the file and right click anywhere in the white space around the model.  Then click on Update Model from Database….  Now, as things go, the stupid model didn’t update for me.  This is something that seems to occur very frequetly with the ADO.NET Entity Framework Model Files.  Since it didn’t update I had to manually right click on the Type Property and then set the Type of the Type (yes I know, redundant naming) to String.

So if anyone from Microsoft is reading this, the entity model files are STILL broken for some reason.  It’s been about 6 months since the entity framework and such where in beta and they still behave in many ways like they’re in beta, please fix this.  k thx bye.

Next I double clicked the Save (buttonSaveToDb) button and entered the following code to write the file data into the database.

private void buttonSaveToDb_Click(object sender, EventArgs e)
{
    if (comboNameType.Text == string.Empty)
    {
        MessageBox.Show("Select a type of name.", "Select Name", MessageBoxButtons.OK,
                        MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
    }
    else
    {
        // TODO Write to DB.
        var generatorEntities = new GeneratorEntities();
        foreach (var name in Names)
        {
            var newName =
                new Names
                    {
                        NameId = Guid.NewGuid(),
                        Name = name,
                        Type = comboNameType.Text
                    };
            generatorEntities.AddToNames(newName);
        }
        generatorEntities.SaveChanges(true);
    }
}

Then a quick reference and that finishes up the TextFileImporter Project.

using Generator.Core.Model;

Now mind you, I broke TDD principles because this app was merely a utility, would be used a few times, and above all breaks isolation and crosses boundaries.  A good rule is to not write tests for a project like this.  Unless you feel it absolutely necessary then I wouldn’t even think of it.

Now run the application and open and import each of the three files into the database.  This will give us the data we need for the next step of our random name generator.

Test Driven Development Built Name Generator Part 1

Part 2Part 3.

This is going to be a multi-part series on building a straight forward database driven name generator.  I’ve tried the random name generator thing and it generally isn’t so great.  I’d tried in the past this idea with the database table of census names and it works great.  So this is part 1.  I’ll post these entries consecutively over the next few days so stay tuned.

First I started a new clean solution and added a test project.  I figured I wasn’t even going to add the actual assembly project yet, just jump right in and start writing a test, get red, and go to the next step.

I added a test file and wrote the following test.

[TestMethod]
public void VerifyFullNameObjectInstantiatesWithNames()
{
    FullName fullName = new FullName();
    Assert.IsTrue(fullName.FirstName.Length == 0);
    Assert.IsTrue(fullName.LastName.Length == 0);
}

After that I used ReSharper Alt+Enter Shortcut plus a little additional keying in myself to flesh out the skeletal class and get a green light.  I ended up with the class below.

public class FullName
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Next I wanted to enforce a contract so I could create a factory to build my FullName objects with.  With that change the interface and class I had now looked like this.

public interface IFullName
{
    string FirstName { get; set; }
    string LastName { get; set; }
}

public class FullName : IFullName
{
    public FullName()
    {
        FirstName = string.Empty;
        LastName = string.Empty;
    }

    public string FirstName { get; set; }
    public string LastName { get; set; }
}

That gave me a green light on my first test.  After that I built a test for the factory that could build the names.

[TestMethod]
public void VerifyFullNameObjectReturnsFromFactory()
{
    IFullName name = NameFactory.Build();
    Assert.IsTrue(name.FirstName.Length > 0);
    Assert.IsTrue(name.LastName.Length > 0);
}

I then took the NameFactory object and fleshed it out so I could build, run the test, and get green lighted.  Below is the NameFactory Class.

public class NameFactory
{
    public static IFullName Build()
    {
        return new FullName { FirstName = "TestFirst", LastName = "TestLast" };
    }
}

So now I have a green light on the name factory.  But even though I have a green light, it doesn’t exactly do what it needs to do, which is get some good unique and random names.  Next step, write a test for getting back some random names.

[TestMethod]
public void VerifyFullNameIsRandom()
{
    IFullName nameOne = NameFactory.Build();
    IFullName nameTwo = NameFactory.Build();

    Assert.AreNotEqual(nameOne.FirstName, nameTwo.FirstName);
    Assert.AreNotEqual(nameOne.LastName, nameTwo.LastName);
}

After creating this test, I have to dive a little deeper.  First I grabbed the census names for first and last names off of the Internet.  After that I added two projects to my overall Visual Studio Solution.  One is a database project and one is Windows App to use to manipulate the text file data and get it into our database.

Next I created the Generator Database a table to store the names that are stored in the files.

The SQL create script is shown below.

 IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Names]') AND type in (N'U'))
 BEGIN
 CREATE TABLE [dbo].[Names](
     [NameId] [uniqueidentifier] NOT NULL,
     [Name] [nvarchar](50) NOT NULL,
     [Type] [smallint] NOT NULL,
  CONSTRAINT [PK_Names] PRIMARY KEY CLUSTERED
 (
     [NameId] ASC
 )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
 ) ON [PRIMARY]
 END

I also added an extended property to outline how I intended to use the “Type” column.

IF NOT EXISTS (SELECT * FROM ::fn_listextendedproperty(N'MS_Description' , N'SCHEMA',N'dbo', N'TABLE',N'Names', N'COLUMN',N'Type'))
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'1 = Male, 2 = Female, 3 = Last Name' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Names', @level2type=N'COLUMN',@level2name=N'Type'

My intention is for the “Type” column to have a 1 for the male first name, a 2 for a female first name, and a 3 for the last name.

I’ve covered creating the initial tests and objects to use.  Also the database table that is needed and the create scripts have been provided.  Next steps are to build a quick app to get the names imported into the database table.  Stay tuned and that will be posted tomorrow.