Monday, March 26, 2018
Boise Code Camp Presentation on Into to Continues Integration
Slides from my Into to TDD talk at Boise Code camp
Tuesday, February 23, 2016
Unit Testing Asp.net MVC View Model Validation
ViewModel attribute validation is a key feature of ASP.NET MVC, but is often not a tested one. For the most part developers verify controller actions, pass in a model, mock the ModelState.IsValid property and call it good, never checking to make sure if the model is validating correctly. One of the biggest reasons is developers just don’t know how, it’s not difficult, but it’s not very intuitive so here is a quick tutorial.
First we take a view model with some basic validation attributes
1: public class RegisterViewModel
2: {
3: [Required]
4: [EmailAddress]
5: [Display(Name = "Email")]
6: public string Email { get; set; }
7:
8: [Required]
9: [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
10: [DataType(DataType.Password)]
11: [Display(Name = "Password")]
12: public string Password { get; set; }
13:
14: [DataType(DataType.Password)]
15: [Display(Name = "Confirm password")]
16: [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
17: public string ConfirmPassword { get; set; }
18: }
Next we create a simple reusable testing context class
1: public abstract class ViewModelValidation_Context<T> where T : new()
2: {
3: public T Target;
4: public List<ValidationResult> ActualMessages;
5: public bool Actual;
6:
7: [SetUp]
8: public void SetUp()
9: {
10: Context();
11: Because();
12: }
13:
14: public virtual void Context()
15: {
16: Target = new T();
17: ActualMessages = new List<ValidationResult>();
18: }
19:
20: public virtual void Because()
21: {
22: var context = new ValidationContext(Target, null, null);
23: Actual = Validator.TryValidateObject(Target, context, ActualMessages, true);
24: }
25: }
Notice this test context class is a little different than what I have used in the past, we are predefining the Because() method. In this case regardless of the class we are testing we are still going to run what is really the meat of this class, we create a Validation Context and then passes it to System.ComponentModel.DataAnnotations.Validator.TryValidateObject and this returns if the view model passed validation and and validation messages.
Next lets put this into action with a test to validate our model
1: [TestFixture]
2: public class When_Testing_RegisterViewModel_Validation_Test : ViewModelValidation_Context<RegisterViewModel>
3: {
4: public override void Context()
5: {
6: base.Context();
7: Target.Email = "TestEmail@email.com";
8: Target.Password = "TestPass";
9: Target.ConfirmPassword = "TestPass";
10: }
11:
12: [Test]
13: public void Passed_Validation_Test()
14: {
15: Assert.IsTrue(Actual);
16: }
17:
18: [Test]
19: public void Has_No_ValidationMessages_Test()
20: {
21: Assert.IsFalse(ActualMessages.Any());
22: }
23: }
The model validation requires we have a valid email, we have a password, a confirm password, and password and confirm password match, in this case everything is good and we get a true for is valid and no validation massages.
Next lets test an invalid model
1: [TestFixture]
2: public class When_Testing_RegisterViewModel_Validation_With_NoPassword_Test : ViewModelValidation_Context<RegisterViewModel>
3: {
4: public override void Context()
5: {
6: base.Context();
7: Target.Email = "TestEmail@email.com";
8: Target.Password = string.Empty;
9: Target.ConfirmPassword = "TestPass";
10: }
11:
12: [Test]
13: public void Fail_Validation_Test()
14: {
15: Assert.IsFalse(Actual);
16: }
17:
18: [Test]
19: public void Has_No_ValidationMessages_Test()
20: {
21: Assert.IsTrue(ActualMessages.Any());
22: }
23:
24: [TestCase("The Password field is required.")]
25: [TestCase("The password and confirmation password do not match.")]
26: public void Has_Expected_Validation_ErrorMessages_Test(string message)
27: {
28: Assert.IsTrue(ActualMessages.Any(x=>x.ErrorMessage== message));
29: }
30:
31: [TestCase("Password")]
32: public void Has_Expected__ValidationMessages_Test(string memberName)
33: {
34: Assert.IsTrue(ActualMessages.Any(x => x.MemberNames.Contains(memberName)));
35: }
36: }
In this test we made password an empty string and as a result it failed validation, and returned a validation message for password being required and for password and confirm password not matching.
Check out my sample application on Github to see this in action.
Thursday, February 18, 2016
I agree With Apple and San Bernardino County is at fault
There is currently a court case in San Bernardino where the FBI is attempting to compel Apple to build an update to IOS that would allow them to access encrypted data on the work phone of Syed Rizwan Farook (Farook and his wife Tashfeen Malik were responsible, authorities say, for killing 14 people and injuring another 22 who were attending a training event and holiday party last December 2 ).
The FBI has requested and has been granted by Magistrate Sheri Pym, in the US District Court of Central California, a court order to force Apple to provide the FBI with software to defeat a self-destruct mechanism on the iPhone. Under the pretense that the phone belongs to the county and the county has the right to access any and all information on their device. To this Tim Cook (CEO of Apple) responded with an open letter to their customers saying they will not comply with the court order. Apple is not disobeying the court order because it supports murdering terrorists, but because they value the rights of their users and are not going to deliberately circumvent their security.
In a statements to Fox News one of the against working the San Bernardino case as stated “Nobody can build a phone that we cannot get in under unique circumstances. Why should Apple be allowed to build a phone that does that?” and “The right should not supersede our ability to keep people safe. It’s why we are not finding others, encryption, and, specifically in this case, we cannot connect the dots.” source. Here is where the DOJ, the FBI and the Judge is wrong and Apple is right. “Our Rights” to not self-incriminate do supersede, and are guaranteed by the constitution. To make this a little more clear the court order is basically the same as getting a court order to force MasterLock to update all of their padlocks to use a master key so the government can open them if they need to.
Regardless of who owns what is being locked, by forcing a company to add security vulnerabilities to their products is wrong, reckless, and fundamentally against everything our country was founded on. I understand the DOJ’s position but they are wrong.
Why San Bernardino is at fault, if you are going to issue devices as a company/government entity (this was a work phone) you should be managing your hardware to protect your assets, this is the basic bus factor. If an employee has a company device, the company owns it, and everything on it. Outside of this case what happens if an employee has valuable company information on a device and the person is in a car wreak? Digital assets, like all assets, need to be managed correctly, the device manufacture should not be forced to weaken their product for your bad planning.
Monday, March 23, 2015
Enterprise Design Patterns and Practices (Boise Code Camp 2015)
Fundamental principals
S.O.L.I.D. Principals
Be strongly typed and loosely coupled
The 2 biggest problems you will face
Golden Hammer
Silver Bullets
Automation, Automation, Automation
Build server & source control
Application Deployment
Database Deployment/Migration
Testing
Instrumentation
Logging
Memory Profiler
Site monitoring and Analytics
Leveraging 3rd party tools
Abstract your 3rd party includes
Building for Extendibility
n-Tier Design
DTO, POCO, and Model objects
Separate Update, Select and Work Logic
Do not over abstract
Building for Scalability
Caching
Spreading the Load
Queuing up
CDN (Content Delivery Network)
Not everything needs to go to the DB or come from it
Redundancy
Tuesday, April 8, 2014
Boise Code Camp 2014
Thursday, November 28, 2013
Testing un-mockable base class methods
To get around this I used a lazy load property and a delegate to create a wrapper.
1: private StartActivityDelegate _start;2: public StartActivityDelegate Start
3: {
4: get { return _start ?? (_start = StartActivity); }
5: set { _start = value; }
6: }
7:
8: public delegate void StartActivityDelegate (Type type);
9:
10: protected override void OnCreate(Bundle bundle)
11: {
12: base.OnCreate(bundle);
13: Redirect();
14: }
15:
16: public void Redirect()
17: {
18: if (Preferences.HasRequired())
19: {
20: Start(typeof(ClientActivity));
21: }
22: else
23: {
24: Start(typeof(SettingsActivity));
25: }
26: }
1: [TestFixture]
2: public class When_Starting_SplashScreen_Without_Required_Preferences_Test
3: {
4: public SplashActivity Target;
5: public Type Actual;
6: public PreferencesMock PreferencesMock;
7:
8: public void TestStartActivity(Type type)
9: {
10: Actual = type;
11: }
12:
13: [SetUp]
14: public void SetUp()
15: {
16: PreferencesMock = new PreferencesMock { HasRequiredStub = false };
17:
18: Target = new SplashActivity { Start = TestStartActivity, Preferences = PreferencesMock };
19: Target.Redirect();
20: }
21:
22: [Test]
23: public void Has_Expected_Activity_Test()
24: {
25: Assert.AreEqual(typeof(SettingsActivity), Actual);
26: }
27: }
1: [TestFixture]
2: public class SplashActivity_Tests
3: {
4: public SplashActivity Target;
5:
6: [SetUp]
7: public void SetUp()
8: {
9: Target = new SplashActivity();
10: }
11:
12: [Test]
13: public void LazyLoads_Write_Test()
14: {
15: MethodInfo actual = Target.Start.GetMethodInfo();
16: MethodInfo expected = typeof(Activity).GetMethod("StartActivity");
17: Assert.AreSame(expected, actual);
18: }
19: }
Wednesday, October 16, 2013
Steps for shortening the “Feedback Loop”
“The secret of getting ahead is
getting started. The secret of getting started is breaking your complex
overwhelming tasks into small manageable tasks, and starting on the first
one.”
|
Step 1: Short Development Iterations
Step 2: Work in Small Teams
Step 3: Test Driven Development
Step 4: Continuous Integration
Step 5: Automate as much as possible
Wednesday, October 9, 2013
Death by Golden Hammer
Monday, October 7, 2013
Having the right tools can make all the difference
Tuesday, January 8, 2013
Tools only give you the ability
Doing unit testing with mocking is a tool, not a silver bullet. Unit tests mixed with behavior testing can be very effective at finding these kinds of bugs and Mocks allow you to create and test against foreseen conditions. While TDD can help expose bugs, unforeseen data conditions can pass though unnoticed, tests only test what they are told to.
Something else to keep in mind is behavior and unit tests are only a small part of the testing tool box that also includes: integration tests, performance tests, automated UI tests, etc. and that’s what these are tools. How effective they are depends on the user, a funny quote I once heard is “A tool runs tools, a craftsman uses them”. You can run your code coverage tool all day long and say “look I have 80% code coverage” but this doesn't mean your code is well tested, it just means it has test that run though it, and can hide untested code.
One commenter on the article said something to the effect that what they where working on requires to much performance to be testable. I would like to state this is B.S. you can make testable code that has just as much performance as not testable code. You may have to change how you test the code, or use different design or testing techniques for example Dependency Injection isn't required to make testable code, if it's not fast enough use greedy constructors or lazy load properties. If you need to make a black box class for performance, you simply do integration tests around it.
In the end, saying TDD isn’t of value because it didn’t catch bug xyz is like a carpenter blaming his hammer for hitting his thumb and not the nail. On the other side it’s just as ridiculous to say “I can build a house” simply because you own a hammer and some nails.
Wednesday, October 17, 2012
Keep contention out of collaboration
There is an old joke “arguing with a developer is like wrestling with a pig in mud, after a while you realizes he/she likes it”, and there are a number of reasons for this, as a group we tend to have strong options, stubbornness, know-it-all, and ego to name a few. Some of this is what makes us good developers, a lot of it is what makes us irrigating to other people.
I personally have been in my fair share of heated, angry, and down right nasty 'discussions' and in the past I may have been guilty of using the force of my will to get teams I have been on to do things 'The right way'. Even joking about being the “a-hole developer”, and as I matured as a professional, I realized even if I win like this, at what cost? I began to realize it was beginning to effect my health and that I didn't like who I was becoming.
We talk about the need to collaborate, from pair programming, sprint planning, daily stand ups, retrospectives, etc. but how often do they turn into arguments? Recently in the Javascript world there has been a lot of arguing about semicolons, and if they should be required. In all honesty this is really a non-problem, and yet people are getting brutal and down right offensive, over the need to be right? Being contentious will not change anyone’s mind, if there is a “winner” it’s because the other side has given up, and at what cost? Both sides are going to be resentful of the other, and it’s going to make working together that much harder.
This is not to say we can’t have discussions from different points of view, have different opinions, be a pushover, or not think the other side is off their rocker. Far from it, but we need to keep it civil and positive. Last I checked we (as developers) are paid to solve problems, not prove we are right. The heart of collaboration is taking different points of view and coming up with the best solution and we can’t do that if we are trying to prove we are right.
It’s ok to have strong opinions, I have more then a few, but it is also important be open minded, be willing to look at what the other side is saying, and come to an acceptable resolution on how to solve the problem. Admitting when you are wrong, or at least not completely right, can be very hard. Ultimately, be willing to work as a team, and if the team decides to do things “wrong” then that’s what the team wants. If you are working with a team that insists on doing things “wrong” and you are unable to contribute, then maybe this isn’t the team for you “If you can’t change where you work, change where you work”.
Wednesday, June 27, 2012
Running your test while you write them using NCrunch
The basic idea is NCrunch automatically runs your tests in a parallel process giving you continuous testing that’s integrated into Visual Studio. It intelligently runs tests automatically so that you don't have to, and gives you useful information including code coverage and performance metrics while you work.
Here is an example of the inline test results
here is a screenshot of the test runner
and this what the coverage looks like
it’s not quite as detailed as I would like, but not bad.
This isn’t going to be a replacement for my copy of Resharper and DotCover but at the same time, I don’t see a problem with running both. This could defiantly save me a lot of time waiting for test to run and if I want more detailed information I can still use dotCover.
This is a free tool that so far has really impressed me, for more information go to the NCrunch home page athttp://www.ncrunch.net/