Commits

Anonymous committed 9e94e0a

Convert from VSTest to Nunit

  • Participants
  • Parent commits 7ca54b2

Comments (0)

Files changed (23)

File OtpSharp.Tests/Data/EmbeddedResourceDataSource.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace OtpSharp.Tests.Data
+{
+    public abstract class EmbeddedResourceDataSource<T> : IEnumerable<T>
+    {
+        protected abstract string EmbededResource { get; }
+        protected abstract T Fill(XElement e);
+        protected abstract string RowElement { get; }
+
+        T[] data;
+
+        public EmbeddedResourceDataSource()
+        {
+            var assembly = typeof(EmbeddedResourceDataSource<T>).Assembly;
+            using (var stream = assembly.GetManifestResourceStream(this.EmbededResource))
+            {
+                var doc = XDocument.Load(stream);
+                var rows = from r in doc.Descendants(this.RowElement)
+                           select this.Fill(r);
+                this.data = rows.ToArray();
+            }
+        }
+
+        private IEnumerable<T> dataElementsEnumerable
+        {
+            get
+            {
+                foreach (var d in this.data)
+                    yield return d;
+            }
+        }
+
+        public IEnumerator<T> GetEnumerator()
+        {
+            return this.dataElementsEnumerable.GetEnumerator();
+        }
+
+        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+        {
+            return this.dataElementsEnumerable.GetEnumerator();
+        }
+    }
+}

File OtpSharp.Tests/Data/Rfc4226AppendixD.xml

+<!--
+Test data from the test value table in RFC 4226 Appendix D
+http://tools.ietf.org/html/rfc4226#appendix-D
+-->
+<Rows>
+  <Row>
+    <counter>0</counter>
+    <decimal>1284755224</decimal>
+    <hotp>755224</hotp>
+  </Row>
+  <Row>
+    <counter>1</counter>
+    <decimal>1094287082</decimal>
+    <hotp>287082</hotp>
+  </Row>
+  <Row>
+    <counter>2</counter>
+    <decimal>137359152</decimal>
+    <hotp>359152</hotp>
+  </Row>
+  <Row>
+    <counter>3</counter>
+    <decimal>1726969429</decimal>
+    <hotp>969429</hotp>
+  </Row>
+  <Row>
+    <counter>4</counter>
+    <decimal>1640338314</decimal>
+    <hotp>338314</hotp>
+  </Row>
+  <Row>
+    <counter>5</counter>
+    <decimal>868254676</decimal>
+    <hotp>254676</hotp>
+  </Row>
+  <Row>
+    <counter>6</counter>
+    <decimal>1918287922</decimal>
+    <hotp>287922</hotp>
+  </Row>
+  <Row>
+    <counter>7</counter>
+    <decimal>82162583</decimal>
+    <hotp>162583</hotp>
+  </Row>
+  <Row>
+    <counter>8</counter>
+    <decimal>673399871</decimal>
+    <hotp>399871</hotp>
+  </Row>
+  <Row>
+    <counter>9</counter>
+    <decimal>645520489</decimal>
+    <hotp>520489</hotp>
+  </Row>
+</Rows>

File OtpSharp.Tests/Data/Rfc4226AppendixDData.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace OtpSharp.Tests.Data
+{
+    public class Rfc4226AppendixDData
+    {
+        readonly string hotpValue;
+        readonly int counterValue;
+        readonly long decimalValue;
+
+        public Rfc4226AppendixDData(string hotp, string counter, string dec)
+        {
+            this.hotpValue = hotp;
+            this.counterValue = int.Parse(counter);
+            this.decimalValue = long.Parse(dec);
+        }
+
+        public string Hotp { get { return this.hotpValue; } }
+        public int Counter { get { return this.counterValue; } }
+        public long Decimal { get { return this.decimalValue; } }
+    }
+}

File OtpSharp.Tests/Data/Rfc4226AppendixDDataSource.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace OtpSharp.Tests.Data
+{
+    public class Rfc4226AppendixDDataSource : EmbeddedResourceDataSource<Rfc4226AppendixDData>
+    {
+        protected override string EmbededResource { get { return "OtpSharp.Tests.Data.Rfc4226AppendixD.xml"; } }
+        protected override string RowElement { get { return "Row"; } }
+
+        protected override Rfc4226AppendixDData Fill(XElement e)
+        {
+            return new Rfc4226AppendixDData(e.Descendants("hotp").First().Value, e.Descendants("counter").First().Value, e.Descendants("decimal").First().Value);
+        }
+    }
+}

File OtpSharp.Tests/Data/Rfc6238AppendixB.xml

+<!--
+RFC 6238 Appendix B provides a table of test TOTP values
+http://tools.ietf.org/html/rfc6238#appendix-B
+-->
+<Rows>
+  <!--
+  |      59     |  1970-01-01  | 0000000000000001 | 94287082 |  SHA1  |
+  |             |   00:00:59   |                  |          |        |
+  |      59     |  1970-01-01  | 0000000000000001 | 46119246 | SHA256 |
+  |             |   00:00:59   |                  |          |        |
+  |      59     |  1970-01-01  | 0000000000000001 | 90693936 | SHA512 |
+  |             |   00:00:59   |                  |          |        |
+  -->
+  <Row>
+    <time>1970-01-01 00:00:59</time>
+    <totp>94287082</totp>
+    <mode>SHA1</mode>
+  </Row>
+  <Row>
+    <time>1970-01-01 00:00:59</time>
+    <totp>46119246</totp>
+    <mode>SHA256</mode>
+  </Row>
+  <Row>
+    <time>1970-01-01 00:00:59</time>
+    <totp>90693936</totp>
+    <mode>SHA512</mode>
+  </Row>
+  <!--
+  |  1111111109 |  2005-03-18  | 00000000023523EC | 07081804 |  SHA1  |
+  |             |   01:58:29   |                  |          |        |
+  |  1111111109 |  2005-03-18  | 00000000023523EC | 68084774 | SHA256 |
+  |             |   01:58:29   |                  |          |        |
+  |  1111111109 |  2005-03-18  | 00000000023523EC | 25091201 | SHA512 |
+  -->
+  <Row>
+    <time>2005-03-18 01:58:29</time>
+    <totp>07081804</totp>
+    <mode>SHA1</mode>
+  </Row>
+  <Row>
+    <time>2005-03-18 01:58:29</time>
+    <totp>68084774</totp>
+    <mode>SHA256</mode>
+  </Row>
+  <Row>
+    <time>2005-03-18 01:58:29</time>
+    <totp>25091201</totp>
+    <mode>SHA512</mode>
+  </Row>
+<!-- 
+  |  1111111111 |  2005-03-18  | 00000000023523ED | 14050471 |  SHA1  |
+  |             |   01:58:31   |                  |          |        |
+  |  1111111111 |  2005-03-18  | 00000000023523ED | 67062674 | SHA256 |
+  |             |   01:58:31   |                  |          |        |
+  |  1111111111 |  2005-03-18  | 00000000023523ED | 99943326 | SHA512 |
+  |             |   01:58:31   |                  |          |        |
+-->
+  <Row>
+    <time>2005-03-18 01:58:31</time>
+    <totp>14050471</totp>
+    <mode>SHA1</mode>
+  </Row>
+  <Row>
+    <time>2005-03-18 01:58:31</time>
+    <totp>67062674</totp>
+    <mode>SHA256</mode>
+  </Row>
+  <Row>
+    <time>2005-03-18 01:58:31</time>
+    <totp>99943326</totp>
+    <mode>SHA512</mode>
+  </Row>
+
+<!--
+  |  1234567890 |  2009-02-13  | 000000000273EF07 | 89005924 |  SHA1  |
+  |             |   23:31:30   |                  |          |        |
+  |  1234567890 |  2009-02-13  | 000000000273EF07 | 91819424 | SHA256 |
+  |             |   23:31:30   |                  |          |        |
+  |  1234567890 |  2009-02-13  | 000000000273EF07 | 93441116 | SHA512 |
+  |             |   23:31:30   |                  |          |        |
+-->
+  
+  <Row>
+    <time>2009-02-13 23:31:30</time>
+    <totp>89005924</totp>
+    <mode>SHA1</mode>
+  </Row>
+  <Row>
+    <time>2009-02-13 23:31:30</time>
+    <totp>91819424</totp>
+    <mode>SHA256</mode>
+  </Row>
+  <Row>
+    <time>2009-02-13 23:31:30</time>
+    <totp>93441116</totp>
+    <mode>SHA512</mode>
+  </Row>
+  
+ <!--
+ |  2000000000 |  2033-05-18  | 0000000003F940AA | 69279037 |  SHA1  |
+  |             |   03:33:20   |                  |          |        |
+  |  2000000000 |  2033-05-18  | 0000000003F940AA | 90698825 | SHA256 |
+  |             |   03:33:20   |                  |          |        |
+  |  2000000000 |  2033-05-18  | 0000000003F940AA | 38618901 | SHA512 |
+ -->
+  <Row>
+    <time>2033-05-18 03:33:20</time>
+    <totp>69279037</totp>
+    <mode>SHA1</mode>
+  </Row>
+  <Row>
+    <time>2033-05-18 03:33:20</time>
+    <totp>90698825</totp>
+    <mode>SHA256</mode>
+  </Row>
+  <Row>
+    <time>2033-05-18 03:33:20</time>
+    <totp>38618901</totp>
+    <mode>SHA512</mode>
+  </Row>
+<!--
+
+  |             |   03:33:20   |                  |          |        |
+  | 20000000000 |  2603-10-11  | 0000000027BC86AA | 65353130 |  SHA1  |
+  |             |   11:33:20   |                  |          |        |
+  | 20000000000 |  2603-10-11  | 0000000027BC86AA | 77737706 | SHA256 |
+  |             |   11:33:20   |                  |          |        |
+  | 20000000000 |  2603-10-11  | 0000000027BC86AA | 47863826 | SHA512 |
+  |             |   11:33:20   |                  |          |        |
+
+-->
+  <Row>
+    <time>2603-10-11 11:33:20</time>
+    <totp>65353130</totp>
+    <mode>SHA1</mode>
+  </Row>
+  <Row>
+    <time>2603-10-11 11:33:20</time>
+    <totp>77737706</totp>
+    <mode>SHA256</mode>
+  </Row>
+  <Row>
+    <time>2603-10-11 11:33:20</time>
+    <totp>47863826</totp>
+    <mode>SHA512</mode>
+  </Row>
+</Rows>

File OtpSharp.Tests/Data/Rfc6238AppendixBData.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace OtpSharp.Tests.Data
+{
+    public class Rfc6238AppendixBData
+    {
+        private readonly string totpValue;
+        private readonly OtpHashMode modeValue;
+        private readonly byte[] rfcTestKeyValue;
+        private readonly DateTime timeValue;
+
+        public Rfc6238AppendixBData(string totp, string mode, string time)
+        {
+            OtpHashMode hashMode;
+            byte[] key;
+            this.GetMode(mode, out hashMode, out key);
+            this.modeValue = hashMode;
+            this.rfcTestKeyValue = key;
+
+            this.totpValue = totp;
+            this.timeValue = DateTime.Parse(time);
+        }
+        
+        public string Totp { get { return this.totpValue; } }
+        public OtpHashMode Mode { get { return this.modeValue; } }
+        public DateTime Time { get { return this.timeValue; } }
+        public IEnumerable<byte> RfcTestKey
+        {
+            get
+            {
+                foreach (byte b in this.rfcTestKeyValue)
+                    yield return b;
+            }
+        }
+
+        private void GetMode(string mode, out OtpHashMode outputMode, out byte[] key)
+        {
+            switch (mode)
+            {
+                case "SHA256":
+                    outputMode = OtpHashMode.Sha256;
+                    key = JoinKeys(32).ToArray();
+                    break;
+                case "SHA512":
+                    outputMode = OtpHashMode.Sha512;
+                    key = JoinKeys(64).ToArray();
+                    break;
+                case "SHA1":
+                    outputMode = OtpHashMode.Sha1;
+                    key = JoinKeys(20).ToArray();
+                    break;
+                default:
+                    throw new Exception("Inavlid mode");
+            }
+        }
+
+        /// <summary>
+        /// Helper method to repeat the test key up to the number of bytes specified
+        /// </summary>
+        private IEnumerable<byte> JoinKeys(int bytes)
+        {
+            int i = 0;
+            do
+            {
+                foreach (var b in OtpCalculationTests.RfcTestKey)
+                {
+                    yield return b;
+                    i++;
+                    if (i >= bytes)
+                        break;
+                }
+            } while (i < bytes);
+        }
+    }
+}

File OtpSharp.Tests/Data/Rfc6238AppendixBDataSource.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace OtpSharp.Tests.Data
+{
+    public class Rfc6238AppendixBDataSource : EmbeddedResourceDataSource<Rfc6238AppendixBData>
+    {
+        protected override string EmbededResource { get { return "OtpSharp.Tests.Data.Rfc6238AppendixB.xml"; } }
+        protected override string RowElement { get { return "Row"; } }
+
+        protected override Rfc6238AppendixBData Fill(System.Xml.Linq.XElement e)
+        {
+            return new Rfc6238AppendixBData(e.Descendants("totp").First().Value,
+                e.Descendants("mode").First().Value,
+                e.Descendants("time").First().Value);
+        }
+    }
+}

File OtpSharp.Tests/KeyGenerationTests.cs

-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
+using NUnit.Framework;
 
 namespace OtpSharp.Tests
 {
-    [TestClass]
+    [TestFixture]
     public class KeyGenerationTests
     {
-        [TestMethod]
+        [Test]
         public void LengthForMode_Sha1()
         {
             Assert.AreEqual(20, KeyGeneration.GenerateRandomKey(OtpHashMode.Sha1).Length);
         }
 
-        [TestMethod]
+        [Test]
         public void LengthForMode_Sha256()
         {
             Assert.AreEqual(32, KeyGeneration.GenerateRandomKey(OtpHashMode.Sha256).Length);
         }
 
-        [TestMethod]
+        [Test]
         public void LengthForMode_Sha512()
         {
             Assert.AreEqual(64, KeyGeneration.GenerateRandomKey(OtpHashMode.Sha512).Length);
         }
 
-        [TestMethod]
+        [Test]
         public void GenerageKey_Zero()
         {
             Assert.AreEqual(0, KeyGeneration.GenerateRandomKey(0).Length);
         }
 
-        [TestMethod]
+        [Test]
         public void GenerageKey_Ten()
         {
             Assert.AreEqual(10, KeyGeneration.GenerateRandomKey(10).Length);
         }
-
-        [TestMethod]
-        public void GenerateKeyFromMaster_1()
-        {
-
-        }
     }
 }

File OtpSharp.Tests/KeyUtilityTests.cs

 using System;
-using System.Collections.Generic;
 using System.Linq;
-using System.Text;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
 using FluentAssertions;
+using NUnit.Framework;
 
 namespace OtpSharp.Tests
 {
-    [TestClass]
+    [TestFixture]
     public class KeyUtilityTests
     {
-        [TestMethod]
+        [Test]
         public void BigEndianInt()
         {
             var data = KeyUtilities.GetBigEndianBytes(1);
             Assert.AreEqual(0x01, data.Last());
         }
 
-        [TestMethod]
+        [Test]
         public void BigEndianLong()
         {
             var data = KeyUtilities.GetBigEndianBytes(1L);
             Assert.AreEqual(0x01, data.Last());
         }
 
-        [TestMethod]
+        [Test]
         public void Destroy_NullArgument()
         {
             new Action(() => KeyUtilities.Destroy(null)).ShouldThrow<ArgumentNullException>().WithMessage("Value cannot be null.\r\nParameter name: sensetiveData");
         }
 
-        [TestMethod]
+        [Test]
         public void Destroy_Empty()
         {
             KeyUtilities.Destroy(new byte[] { }); // just make sure this doesn't blow up
         }
 
-        [TestMethod]
+        [Test]
         public void Destroy_Success()
         {
             var testKey = OtpCalculationTests.RfcTestKey;

File OtpSharp.Tests/NtpTests.cs

-using Microsoft.VisualStudio.TestTools.UnitTesting;
+using NUnit.Framework;
 using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
 
 namespace OtpSharp.Tests
 {
-    [TestClass]
+    [TestFixture]
     public class NtpTests
     {
-        [TestMethod]
+        [Test]
         public void NistParse_Success()
         {
             var response = @"
             Assert.AreEqual(new DateTime(2013, 2, 5, 18, 41, 11), time, "time doesn't match");
         }
 
-        [TestMethod]
+        [Test]
         public void NistParse_NoUtc()
         {
             DateTime time;
             Assert.AreEqual(DateTime.MinValue, time);
         }
 
-        [TestMethod]
+        [Test]
         public void NistParse_NoRegexMatch()
         {
             DateTime time;

File OtpSharp.Tests/OtpCalculationTests.cs

-using System;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
+using NUnit.Framework;
+using OtpSharp.Tests.Data;
+using System;
+using System.Collections.Generic;
 using System.Linq;
-using System.Collections.Generic;
 
 namespace OtpSharp.Tests
 {
     /// http://tools.ietf.org/html/rfc4226#appendix-D
     /// http://tools.ietf.org/html/rfc6238#appendix-B
     /// </remarks>
-    [TestClass]
+    [TestFixture]
     public class OtpCalculationTests
     {
         /// <summary>
         /// </summary>
         public TestContext TestContext { get; set; }
 
-        [TestMethod]
-        [DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML",
-            "|DataDirectory|\\Rfc4226AppendixD.xml",
-            "Row",
-            DataAccessMethod.Sequential)]
-        [DeploymentItem("Rfc4226AppendixD.xml")]
-        public void OtpAppendixDTests()
+        [Test]
+        [TestCaseSource(typeof(Rfc4226AppendixDDataSource))]
+        public void OtpAppendixDTests(Rfc4226AppendixDData data)
         {
-            // test values from RFC - Appendix D
-            long counter = Convert.ToInt64(this.TestContext.DataRow["counter"]);
-            long expectedResult = Convert.ToInt64(this.TestContext.DataRow["decimal"]);
+            Assert.IsNotNull(data, "data was null");
 
             Hotp hotpCalculator = new Hotp(RfcTestKey);
-            var otp = hotpCalculator.ComputeHotpDecimal(counter, OtpHashMode.Sha1);
+            var otp = hotpCalculator.ComputeHotpDecimal(data.Counter, OtpHashMode.Sha1);
 
-            Assert.AreEqual(expectedResult, otp);
+            Assert.AreEqual(data.Decimal, otp);
         }
 
-        [TestMethod]
-        [DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML",
-            "|DataDirectory|\\Rfc4226AppendixD.xml",
-            "Row",
-            DataAccessMethod.Sequential)]
-        [DeploymentItem("Rfc4226AppendixD.xml")]
-        public void HotpAppendixDTests()
+        [Test]
+        [TestCaseSource(typeof(Rfc4226AppendixDDataSource))]
+        public void HotpAppendixDTests(Rfc4226AppendixDData data)
         {
-            // test values from RFC - Appendix D
-            long counter = Convert.ToInt64(this.TestContext.DataRow["counter"]);
-            string expectedResult = (string)this.TestContext.DataRow["hotp"];
-
+            Assert.IsNotNull(data, "data was null");
             Hotp hotpCalculator = new Hotp(RfcTestKey);
-            var hotp = hotpCalculator.ComputeHotp(counter);
-
-            Assert.AreEqual(expectedResult, hotp);
+            var hotp = hotpCalculator.ComputeHotp(data.Counter);
+            Assert.AreEqual(data.Hotp, hotp);
         }
 
-        [TestMethod]
-        [DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML",
-            "|DataDirectory|\\Rfc4226AppendixD.xml",
-            "Row",
-            DataAccessMethod.Sequential)]
-        [DeploymentItem("Rfc4226AppendixD.xml")]
-        public void HotpAppendixDTests_ProtectedKey()
+        [Test]
+        [TestCaseSource(typeof(Rfc4226AppendixDDataSource))]
+        public void HotpAppendixDTests_ProtectedKey(Rfc4226AppendixDData data)
         {
-            // test values from RFC - Appendix D
-            long counter = Convert.ToInt64(this.TestContext.DataRow["counter"]);
-            string expectedResult = (string)this.TestContext.DataRow["hotp"];
+            Assert.IsNotNull(data, "data was null");
 
             Hotp hotpCalculator = new Hotp(new InMemoryKey(RfcTestKey));
-            var hotp = hotpCalculator.ComputeHotp(counter);
+            var hotp = hotpCalculator.ComputeHotp(data.Counter);
 
-            Assert.AreEqual(expectedResult, hotp);
+            Assert.AreEqual(data.Hotp, hotp);
         }
 
-        [TestMethod]
-        [DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML",
-            "|DataDirectory|\\Rfc6238AppendixB.xml",
-            "Row",
-            DataAccessMethod.Sequential)]
-        [DeploymentItem("Rfc6238AppendixB.xml")]
-        public void TotpAppendixBTests()
+        [Test]
+        [TestCaseSource(typeof(Rfc6238AppendixBDataSource))]
+        public void TotpAppendixBTests(Rfc6238AppendixBData data)
         {
-            // test values from RFC - Appendix D
-            var time = DateTime.Parse((string)this.TestContext.DataRow["time"]);
-            string expectedResult = (string)this.TestContext.DataRow["totp"];
+            Assert.IsNotNull(data, "data was null");
+            var totpCalculator = new Totp(data.RfcTestKey.ToArray(), mode: data.Mode, totpSize: 8);
+            var totp = totpCalculator.ComputeTotp(data.Time);
 
-            OtpHashMode mode;
-            byte[] key;
-            GetMode((string)this.TestContext.DataRow["mode"], out mode, out key);
-
-            var totpCalculator = new Totp(key, mode: mode, totpSize: 8);
-            var hotp = totpCalculator.ComputeTotp(time);
-
-            Assert.AreEqual(expectedResult, hotp);
+            Assert.AreEqual(data.Totp, totp);
         }
 
-        [TestMethod]
-        [DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML",
-            "|DataDirectory|\\Rfc6238AppendixB.xml",
-            "Row",
-            DataAccessMethod.Sequential)]
-        [DeploymentItem("Rfc6238AppendixB.xml")]
-        public void TotpAppendixBTests_ProtectedKey()
+        [Test]
+        [TestCaseSource(typeof(Rfc6238AppendixBDataSource))]
+        public void TotpAppendixBTests_ProtectedKey(Rfc6238AppendixBData data)
         {
-            // test values from RFC - Appendix D
-            var time = DateTime.Parse((string)this.TestContext.DataRow["time"]);
-            string expectedResult = (string)this.TestContext.DataRow["totp"];
+            Assert.IsNotNull(data, "data was null");
 
-            OtpHashMode mode;
-            byte[] key;
-            GetMode((string)this.TestContext.DataRow["mode"], out mode, out key);
+            var totpCalculator = new Totp(new InMemoryKey(data.RfcTestKey.ToArray()), mode: data.Mode, totpSize: 8);
+            var totp = totpCalculator.ComputeTotp(data.Time);
 
-            var totpCalculator = new Totp(new InMemoryKey(key), mode: mode, totpSize: 8);
-            var hotp = totpCalculator.ComputeTotp(time);
-
-            Assert.AreEqual(expectedResult, hotp);
+            Assert.AreEqual(data.Totp, totp);
         }
 
         /// <summary>
         /// Ensures that the padding is correct
         /// </summary>
-        [TestMethod]
+        [Test]
         public void HotpPaddingTest()
         {
             var hotpCalculator = new Hotp(RfcTestKey);
         /// <summary>
         /// Ensures that the padding is correct
         /// </summary>
-        [TestMethod]
+        [Test]
         public void Totp8DigitPaddingTest()
         {
-            var totpCalculator = new Totp(RfcTestKey, totpSize:8);
+            var totpCalculator = new Totp(RfcTestKey, totpSize: 8);
             var date = new DateTime(1970, 1, 19, 13, 23, 00);
             var totp = totpCalculator.ComputeTotp(date);
             Assert.AreEqual("00003322", totp);
         /// <summary>
         /// Ensures that the padding is correct
         /// </summary>
-        [TestMethod]
+        [Test]
         public void Totp6DigitPaddingTest()
         {
             var totpCalculator = new Totp(RfcTestKey, totpSize: 6);
             var totp = totpCalculator.ComputeTotp(date);
             Assert.AreEqual("003322", totp);
         }
-
-        private void GetMode(string mode, out OtpHashMode outputMode, out byte[] key)
-        {
-            switch (mode)
-            {
-                case "SHA256":
-                    outputMode = OtpHashMode.Sha256;
-                    key = JoinKeys(32).ToArray();
-                    break;
-                case "SHA512":
-                    outputMode = OtpHashMode.Sha512;
-                    key = JoinKeys(64).ToArray();
-                    break;
-                case "SHA1":
-                    outputMode = OtpHashMode.Sha1;
-                    key = JoinKeys(20).ToArray();
-                    break;
-                default:
-                    throw new Exception("Inavlid mode");
-            }
-        }
-
-        /// <summary>
-        /// Helper method to repeat the test key up to the number of bytes specified
-        /// </summary>
-        private IEnumerable<byte> JoinKeys(int bytes)
-        {
-            int i = 0;
-            do
-            {
-                foreach (var b in RfcTestKey)
-                {
-                    yield return b;
-                    i++;
-                    if (i >= bytes)
-                        break;
-                }
-            } while (i < bytes);
-        }
     }
 }

File OtpSharp.Tests/OtpClassValidationTests.cs

-using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System;
+using System;
+using FluentAssertions;
+using NUnit.Framework;
 
 namespace OtpSharp.Tests
 {
-    [TestClass]
+    [TestFixture]
     public class OtpClassValidationTests
     {
-        [TestMethod]
+        [Test]
         public void ContractTestKeySize_Success()
         {
             var t = new Totp(OtpCalculationTests.RfcTestKey);
         }
 
-        [TestMethod]
+        [Test]
         public void ContractTestKeySize_Null()
         {
             byte[] key = null;
             new Action(() => new Totp(key)).ShouldThrow<ArgumentNullException>().WithMessage("Value cannot be null.\r\nParameter name: secretKey"); ;
         }
 
-        [TestMethod]
+        [Test]
         public void ContractTestKeySize_InMemoryKeyNull()
         {
             InMemoryKey key = null;
             new Action(() => new Totp(key)).ShouldThrow<ArgumentNullException>().WithMessage("Value cannot be null.\r\nParameter name: secretKey"); ;
         }
 
-        [TestMethod]
+        [Test]
         public void ContractTestKeySize_Empty()
         {
             new Action(() => new Totp(new byte[] { })).ShouldThrow<ArgumentException>().WithMessage("secretKey empty");
         }
 
-        [TestMethod]
+        [Test]
         public void ContractTestKeySize_ProtectedKeyEmpty()
         {
             new Action(() => new Totp(new InMemoryKey(new byte[] { }))).ShouldThrow<ArgumentException>().WithMessage("The key must not be empty");
         }
 
-        [TestMethod]
+        [Test]
         public void StepSize_Zero()
         {
             new Action(() => new Totp(OtpCalculationTests.RfcTestKey, step: 0)).ShouldThrow<ArgumentOutOfRangeException>().WithMessage("Specified argument was out of the range of valid values.\r\nParameter name: step");
         }
 
-        [TestMethod]
+        [Test]
         public void StepSize_Negative()
         {
             new Action(() => new Totp(OtpCalculationTests.RfcTestKey, step: -1)).ShouldThrow<ArgumentOutOfRangeException>().WithMessage("Specified argument was out of the range of valid values.\r\nParameter name: step");
         }
 
-        [TestMethod]
+        [Test]
         public void StepSize_Fifteen()
         {
             var t = new Totp(OtpCalculationTests.RfcTestKey, step: 15);
         }
 
-        [TestMethod]
+        [Test]
         public void Digits_Zero()
         {
             new Action(() => new Totp(OtpCalculationTests.RfcTestKey, totpSize: 0)).ShouldThrow<ArgumentOutOfRangeException>().WithMessage("Specified argument was out of the range of valid values.\r\nParameter name: totpSize"); ;
         }
 
-        [TestMethod]
+        [Test]
         public void Digits_Negative()
         {
             new Action(() => new Totp(OtpCalculationTests.RfcTestKey, totpSize: -1)).ShouldThrow<ArgumentOutOfRangeException>().WithMessage("Specified argument was out of the range of valid values.\r\nParameter name: totpSize"); ;
         }
 
-        [TestMethod]
+        [Test]
         public void Digits_Eleven()
         {
             new Action(() => new Totp(OtpCalculationTests.RfcTestKey, totpSize: 11)).ShouldThrow<ArgumentOutOfRangeException>().WithMessage("Specified argument was out of the range of valid values.\r\nParameter name: totpSize"); ;
         }
 
-        [TestMethod]
+        [Test]
         public void Digits_Ten()
         {
             var t = new Totp(OtpCalculationTests.RfcTestKey, totpSize: 10);

File OtpSharp.Tests/OtpKeyInteractionTests.cs

-using System;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Moq;
+using Moq;
+using NUnit.Framework;
+using System;
 
 namespace OtpSharp.Tests
 {
-    [TestClass]
+    [TestFixture]
     public class OtpKeyInteractionTests
     {
         private Mock<IKeyProvider> keyMock
         private const long hotpCounter = 1;
         private readonly byte[] hotpData = KeyUtilities.GetBigEndianBytes(1L);
 
-        [TestMethod]
+        [Test]
         public void Totp_Sha1_Default_Called()
         {
             var mock = this.keyMock;
             mock.Verify(k => k.ComputeHmac(OtpHashMode.Sha1, totpData));
         }
 
-        [TestMethod]
+        [Test]
         public void Totp_Sha1_Called()
         {
             var mock = this.keyMock;
             mock.Verify(k => k.ComputeHmac(OtpHashMode.Sha1, totpData));
         }
 
-        [TestMethod]
+        [Test]
         public void Totp_Sha256_Called()
         {
             var mock = this.keyMock;
             mock.Verify(k => k.ComputeHmac(OtpHashMode.Sha256, totpData));
         }
 
-        [TestMethod]
+        [Test]
         public void Totp_Sha512_Called()
         {
             var mock = this.keyMock;
             mock.Verify(k => k.ComputeHmac(OtpHashMode.Sha512, totpData));
         }
 
-        [TestMethod]
+        [Test]
         public void Hotp_Sha1_Default_Called()
         {
             var mock = this.keyMock;
             mock.Verify(k => k.ComputeHmac(OtpHashMode.Sha1, hotpData));
         }
 
-        [TestMethod]
+        [Test]
         public void Hotp_Sha1_Called()
         {
             var mock = this.keyMock;
             mock.Verify(k => k.ComputeHmac(OtpHashMode.Sha1, hotpData));
         }
 
-        [TestMethod]
+        [Test]
         public void Hotp_Sha256_Called()
         {
             var mock = this.keyMock;
             mock.Verify(k => k.ComputeHmac(OtpHashMode.Sha256, hotpData));
         }
 
-        [TestMethod]
+        [Test]
         public void Hotp_Sha512_Called()
         {
             var mock = this.keyMock;

File OtpSharp.Tests/OtpSharp.Tests.csproj

     <Reference Include="FluentAssertions">
       <HintPath>..\packages\FluentAssertions.2.0.1\lib\net40\FluentAssertions.dll</HintPath>
     </Reference>
-    <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
     <Reference Include="Moq">
       <HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
     </Reference>
+    <Reference Include="nunit.framework">
+      <HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
+    </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core">
       <RequiredTargetFramework>3.5</RequiredTargetFramework>
     <Reference Include="System.Xml.Linq" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="Data\EmbeddedResourceDataSource.cs" />
+    <Compile Include="Data\Rfc4226AppendixDData.cs" />
+    <Compile Include="Data\Rfc4226AppendixDDataSource.cs" />
+    <Compile Include="Data\Rfc6238AppendixBData.cs" />
+    <Compile Include="Data\Rfc6238AppendixBDataSource.cs" />
     <Compile Include="KeyGenerationTests.cs" />
     <Compile Include="KeyUtilityTests.cs" />
     <Compile Include="NtpTests.cs" />
     </ProjectReference>
   </ItemGroup>
   <ItemGroup>
-    <Content Include="Rfc4226AppendixD.xml">
-      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
-    </Content>
-    <Content Include="Rfc6238AppendixB.xml">
-      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
-    </Content>
+    <EmbeddedResource Include="Data\Rfc4226AppendixD.xml" />
+    <EmbeddedResource Include="Data\Rfc6238AppendixB.xml" />
   </ItemGroup>
   <ItemGroup>
     <None Include="packages.config" />

File OtpSharp.Tests/ProtectedKeyTests.cs

 using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
+using NUnit.Framework;
 using System;
 using System.Security.Cryptography;
 
 namespace OtpSharp.Tests
 {
-    [TestClass]
+    [TestFixture]
     public class ProtectedKeyTests
     {
-        [TestMethod]
+        [Test]
         public void ProtectedKey_Empty()
         {
             new Action(() => new InMemoryKey(new byte[] { }))
                 .WithMessage("The key must not be empty");
         }
 
-        [TestMethod]
+        [Test]
         public void ProtectedKey_Null()
         {
             new Action(() => new InMemoryKey(null))
                 .WithMessage("Value cannot be null.\r\nParameter name: key");
         }
 
-        [TestMethod]
+        [Test]
         public void ProtectedKey_Basic()
         {
             var pk = new InMemoryKey(OtpCalculationTests.RfcTestKey);
             CollectionAssert.AreEqual(OtpCalculationTests.RfcTestKey, pk.GetCopyOfKey());
         }
 
-        [TestMethod]
+        [Test]
         public void ProtectedKey_WipeReference()
         {
             var key = OtpCalculationTests.RfcTestKey;
         /// into the constructor with random garbage.  This test is to ensure that behavior
         /// isn't present anymore.
         /// </remarks>
-        [TestMethod]
+        [Test]
         public void ProtectedKey_EnsureOriginalkeyIntegrity()
         {
             var key = OtpCalculationTests.RfcTestKey;
             CollectionAssert.AreEqual(OtpCalculationTests.RfcTestKey, key);
         }
 
-        [TestMethod]
+        [Test]
         public void ProtectedKey_ProtectKey()
         {
             var originalKey = KeyGeneration.GenerateRandomKey(16);
             CollectionAssert.AreEqual(originalKey, pk.GetCopyOfKey());
         }
 
-        [TestMethod]
+        [Test]
         public void ProtectedKey_ProtectKey_CrossProcess()
         {
             var originalKey = KeyGeneration.GenerateRandomKey(16);
             CollectionAssert.AreEqual(originalKey, pk.GetCopyOfKey());
         }
 
-        [TestMethod]
+        [Test]
         public void ProtectedKey_ProtectKey_SameLogon()
         {
             var originalKey = KeyGeneration.GenerateRandomKey(16);
             CollectionAssert.AreEqual(originalKey, pk.GetCopyOfKey());
         }
 
-        [TestMethod]
+        [Test]
         public void ProtectedKey_ProtectKeyEmpty()
         {
             new Action(() => InMemoryKey.CreateProtectedKeyFromPreProtectedMemory(new byte[] { }, 16, MemoryProtectionScope.SameProcess))
                 WithMessage("The key must not be empty");
         }
 
-        [TestMethod]
+        [Test]
         public void ProtectedKey_ProtectKeyZeroLength()
         {
             new Action(() => InMemoryKey.CreateProtectedKeyFromPreProtectedMemory(OtpCalculationTests.RfcTestKey, 0, MemoryProtectionScope.SameProcess))
                 .WithMessage("The key must not be empty");
         }
 
-        [TestMethod]
+        [Test]
         public void ProtectedKey_ProtectKeyNull()
         {
             new Action(() => InMemoryKey.CreateProtectedKeyFromPreProtectedMemory(null, 16, MemoryProtectionScope.SameProcess))
                 .WithMessage("Value cannot be null.\r\nParameter name: preProtectedKey");
         }
 
-        [TestMethod]
+        [Test]
         public void ProtectedKey_MultipleUse()
         {
             var originalKey = KeyGeneration.GenerateRandomKey(16);
                 CollectionAssert.AreEqual(originalKey, pk.GetCopyOfKey());
         }
 
-        [TestMethod]
+        [Test]
         public void ProtectedKey_ProtectKeyWithSpecificLength()
         {
             var originalKey = KeyGeneration.GenerateRandomKey(20);

File OtpSharp.Tests/ReflectiveExtensions.cs

-using System;
-using System.Collections.Generic;
-using System.Linq;
+using NUnit.Framework;
 using System.Reflection;
-using System.Text;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
 
 namespace OtpSharp.Tests
 {

File OtpSharp.Tests/Rfc4226AppendixD.xml

-<!--
-Test data from the test value table in RFC 4226 Appendix D
-http://tools.ietf.org/html/rfc4226#appendix-D
--->
-<Rows>
-  <Row>
-    <counter>0</counter>
-    <decimal>1284755224</decimal>
-    <hotp>755224</hotp>
-  </Row>
-  <Row>
-    <counter>1</counter>
-    <decimal>1094287082</decimal>
-    <hotp>287082</hotp>
-  </Row>
-  <Row>
-    <counter>2</counter>
-    <decimal>137359152</decimal>
-    <hotp>359152</hotp>
-  </Row>
-  <Row>
-    <counter>3</counter>
-    <decimal>1726969429</decimal>
-    <hotp>969429</hotp>
-  </Row>
-  <Row>
-    <counter>4</counter>
-    <decimal>1640338314</decimal>
-    <hotp>338314</hotp>
-  </Row>
-  <Row>
-    <counter>5</counter>
-    <decimal>868254676</decimal>
-    <hotp>254676</hotp>
-  </Row>
-  <Row>
-    <counter>6</counter>
-    <decimal>1918287922</decimal>
-    <hotp>287922</hotp>
-  </Row>
-  <Row>
-    <counter>7</counter>
-    <decimal>82162583</decimal>
-    <hotp>162583</hotp>
-  </Row>
-  <Row>
-    <counter>8</counter>
-    <decimal>673399871</decimal>
-    <hotp>399871</hotp>
-  </Row>
-  <Row>
-    <counter>9</counter>
-    <decimal>645520489</decimal>
-    <hotp>520489</hotp>
-  </Row>
-</Rows>

File OtpSharp.Tests/Rfc6238AppendixB.xml

-<!--
-RFC 6238 Appendix B provides a table of test TOTP values
-http://tools.ietf.org/html/rfc6238#appendix-B
--->
-<Rows>
-  <!--
-  |      59     |  1970-01-01  | 0000000000000001 | 94287082 |  SHA1  |
-  |             |   00:00:59   |                  |          |        |
-  |      59     |  1970-01-01  | 0000000000000001 | 46119246 | SHA256 |
-  |             |   00:00:59   |                  |          |        |
-  |      59     |  1970-01-01  | 0000000000000001 | 90693936 | SHA512 |
-  |             |   00:00:59   |                  |          |        |
-  -->
-  <Row>
-    <time>1970-01-01 00:00:59</time>
-    <totp>94287082</totp>
-    <mode>SHA1</mode>
-  </Row>
-  <Row>
-    <time>1970-01-01 00:00:59</time>
-    <totp>46119246</totp>
-    <mode>SHA256</mode>
-  </Row>
-  <Row>
-    <time>1970-01-01 00:00:59</time>
-    <totp>90693936</totp>
-    <mode>SHA512</mode>
-  </Row>
-  <!--
-  |  1111111109 |  2005-03-18  | 00000000023523EC | 07081804 |  SHA1  |
-  |             |   01:58:29   |                  |          |        |
-  |  1111111109 |  2005-03-18  | 00000000023523EC | 68084774 | SHA256 |
-  |             |   01:58:29   |                  |          |        |
-  |  1111111109 |  2005-03-18  | 00000000023523EC | 25091201 | SHA512 |
-  -->
-  <Row>
-    <time>2005-03-18 01:58:29</time>
-    <totp>07081804</totp>
-    <mode>SHA1</mode>
-  </Row>
-  <Row>
-    <time>2005-03-18 01:58:29</time>
-    <totp>68084774</totp>
-    <mode>SHA256</mode>
-  </Row>
-  <Row>
-    <time>2005-03-18 01:58:29</time>
-    <totp>25091201</totp>
-    <mode>SHA512</mode>
-  </Row>
-<!-- 
-  |  1111111111 |  2005-03-18  | 00000000023523ED | 14050471 |  SHA1  |
-  |             |   01:58:31   |                  |          |        |
-  |  1111111111 |  2005-03-18  | 00000000023523ED | 67062674 | SHA256 |
-  |             |   01:58:31   |                  |          |        |
-  |  1111111111 |  2005-03-18  | 00000000023523ED | 99943326 | SHA512 |
-  |             |   01:58:31   |                  |          |        |
--->
-  <Row>
-    <time>2005-03-18 01:58:31</time>
-    <totp>14050471</totp>
-    <mode>SHA1</mode>
-  </Row>
-  <Row>
-    <time>2005-03-18 01:58:31</time>
-    <totp>67062674</totp>
-    <mode>SHA256</mode>
-  </Row>
-  <Row>
-    <time>2005-03-18 01:58:31</time>
-    <totp>99943326</totp>
-    <mode>SHA512</mode>
-  </Row>
-
-<!--
-  |  1234567890 |  2009-02-13  | 000000000273EF07 | 89005924 |  SHA1  |
-  |             |   23:31:30   |                  |          |        |
-  |  1234567890 |  2009-02-13  | 000000000273EF07 | 91819424 | SHA256 |
-  |             |   23:31:30   |                  |          |        |
-  |  1234567890 |  2009-02-13  | 000000000273EF07 | 93441116 | SHA512 |
-  |             |   23:31:30   |                  |          |        |
--->
-  
-  <Row>
-    <time>2009-02-13 23:31:30</time>
-    <totp>89005924</totp>
-    <mode>SHA1</mode>
-  </Row>
-  <Row>
-    <time>2009-02-13 23:31:30</time>
-    <totp>91819424</totp>
-    <mode>SHA256</mode>
-  </Row>
-  <Row>
-    <time>2009-02-13 23:31:30</time>
-    <totp>93441116</totp>
-    <mode>SHA512</mode>
-  </Row>
-  
- <!--
- |  2000000000 |  2033-05-18  | 0000000003F940AA | 69279037 |  SHA1  |
-  |             |   03:33:20   |                  |          |        |
-  |  2000000000 |  2033-05-18  | 0000000003F940AA | 90698825 | SHA256 |
-  |             |   03:33:20   |                  |          |        |
-  |  2000000000 |  2033-05-18  | 0000000003F940AA | 38618901 | SHA512 |
- -->
-  <Row>
-    <time>2033-05-18 03:33:20</time>
-    <totp>69279037</totp>
-    <mode>SHA1</mode>
-  </Row>
-  <Row>
-    <time>2033-05-18 03:33:20</time>
-    <totp>90698825</totp>
-    <mode>SHA256</mode>
-  </Row>
-  <Row>
-    <time>2033-05-18 03:33:20</time>
-    <totp>38618901</totp>
-    <mode>SHA512</mode>
-  </Row>
-<!--
-
-  |             |   03:33:20   |                  |          |        |
-  | 20000000000 |  2603-10-11  | 0000000027BC86AA | 65353130 |  SHA1  |
-  |             |   11:33:20   |                  |          |        |
-  | 20000000000 |  2603-10-11  | 0000000027BC86AA | 77737706 | SHA256 |
-  |             |   11:33:20   |                  |          |        |
-  | 20000000000 |  2603-10-11  | 0000000027BC86AA | 47863826 | SHA512 |
-  |             |   11:33:20   |                  |          |        |
-
--->
-  <Row>
-    <time>2603-10-11 11:33:20</time>
-    <totp>65353130</totp>
-    <mode>SHA1</mode>
-  </Row>
-  <Row>
-    <time>2603-10-11 11:33:20</time>
-    <totp>77737706</totp>
-    <mode>SHA256</mode>
-  </Row>
-  <Row>
-    <time>2603-10-11 11:33:20</time>
-    <totp>47863826</totp>
-    <mode>SHA512</mode>
-  </Row>
-</Rows>

File OtpSharp.Tests/TimeCorrectionTests.cs

-using System;
-using System.Threading;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
+using NUnit.Framework;
+using System;
 
 namespace OtpSharp.Tests
 {
     /// If there is a failure re-run the test and report a bug and we'll consider moving to mocks.  Haven't seen it yet but it is 
     /// possible if the the time the test is run and thread scheduler conspire against the test.
     /// </remarks>
-    [TestClass]
+    [TestFixture]
     public class TimeCorrectionTests
     {
-        [TestMethod]
+        [Test]
         public void TimeCorrection_BasicWithSpecificReference()
         {
             var baseTime = DateTime.UtcNow;
             Assert.AreEqual(TimeSpan.FromMilliseconds(-12500), correction.CorrectionFactor);
         }
 
-        [TestMethod]
+        [Test]
         public void TimeCorrection_Basic()
         {
             var hypotheticallyCorrectUtcTime = DateTime.UtcNow.AddMilliseconds(12500);
             Assert.IsTrue(Math.Abs(difference.TotalMilliseconds) <= 64, "The corrected value is wrong");
         }
 
-        [TestMethod]
+        [Test]
         public void TimeCorrection_UncorrectedInstanceSpecificReference()
         {
             var baseTime = DateTime.UtcNow;
             Assert.AreEqual(baseTime, TimeCorrection.UncorrectedInstance.GetCorrectedTime(baseTime));
         }
 
-        [TestMethod]
+        [Test]
         public void TimeCorrection_TotpWithCorrectionRemainingSeconds()
         {
             var correction = new TimeCorrection(DateTime.UtcNow.AddSeconds(5));
             Assert.AreEqual(5, difference);
         }
 
-        [TestMethod]
+        [Test]
         public void TimeCorrection_TotpWithCorrectionGeneration()
         {
             var correction = new TimeCorrection(DateTime.UtcNow.AddSeconds(100)); // 100 ensures that at a minimum we are 3 steps away
             Assert.AreEqual(uncorrectedCode, correctedCode);
         }
 
-        [TestMethod]
+        [Test]
         public void TimeCorrection_TotpWithCorrectionVerification()
         {
             var correction = new TimeCorrection(DateTime.UtcNow.AddSeconds(100)); // 100 ensures that at a minimum we are 3 steps away
             Assert.AreEqual(uncorrectedStep, correctedStep);
         }
 
-        [TestMethod]
+        [Test]
         public void TimeCorrection_TotpRemainingSecondsSpecificDateWithCorrection()
         {
             var correction = new TimeCorrection(DateTime.UtcNow.AddSeconds(15));
             Assert.AreEqual(specificRemaining, utcRemaining, "The 2 remaining seconds overloads didn't produce the same results");
         }
 
-        [TestMethod]
+        [Test]
         public void TimeCorrection_TotpComputeTotpSpecificDateWithCorrection()
         {
             var correction = new TimeCorrection(DateTime.UtcNow.AddSeconds(100)); // 100 ensures that at a minimum we are 3 steps away
             Assert.AreEqual(specificCode, utcCode, "The 2 compute totp overloads didn't produce the same results");
         }
 
-        [TestMethod]
+        [Test]
         public void TimeCorrection_TotpVerifyTotpSpecificDateWithCorrection()
         {
             var correction = new TimeCorrection(DateTime.UtcNow.AddSeconds(100)); // 100 ensures that at a minimum we are 3 steps away

File OtpSharp.Tests/TotpVerification.cs

-using System;
-using System.Text;
-using System.Collections.Generic;
-using System.Linq;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
+using NUnit.Framework;
+using System;
 using System.Threading;
 
 namespace OtpSharp.Tests
 {
-    [TestClass]
+    [TestFixture]
     public class TotpVerification
     {
         DateTime testTime = new DateTime(2009, 2, 13, 23, 31, 30);
 
-        [TestMethod]
+        [Test]
         public void ExactMatch_SpecificVerificationWindow()
         {
             var verificationWindow = new VerificationWindow();
             AssertWindow(verificationWindow);
         }
 
-        [TestMethod]
+        [Test]
         public void ExactMatch_SpecificVerificationWindowWithPriors()
         {
             var verificationWindow = new VerificationWindow(previous: 1);
             AssertWindow(verificationWindow);
         }
 
-        [TestMethod]
+        [Test]
         public void ExactMatch_NullVerificationWindow()
         {
             VerificationWindow verificationWindow = null;
             AssertWindow(verificationWindow);
         }
 
-        [TestMethod]
+        [Test]
         public void PreviousMatch_SpecificVerificationWindow()
         {
             var verificationWindow = new VerificationWindow(previous: 1);
             AssertWindow(verificationWindow, -1);
         }
 
-        [TestMethod]
+        [Test]
         public void PreviousNonMatch_SpecificVerificationWindow()
         {
             var verificationWindow = new VerificationWindow();
             AssertWindow(verificationWindow, -1, false);
         }
 
-        [TestMethod]
+        [Test]
         public void FutureMatch_SpecificVerificationWindow()
         {
             var verificationWindow = new VerificationWindow(future: 1);
             AssertWindow(verificationWindow, 1);
         }
 
-        [TestMethod]
+        [Test]
         public void FutureNonMatch_SpecificVerificationWindow()
         {
             var verificationWindow = new VerificationWindow();
             AssertWindow(verificationWindow, 1, false);
         }
 
-        [TestMethod]
+        [Test]
         public void ExactMatch_SpecificVerificationWindowUtcTime()
         {
             var totp = new Totp(OtpCalculationTests.RfcTestKey);
                 Assert.IsFalse(success);
         }
 
-        [TestMethod]
+        [Test]
         public void Totp_EnsureKeyIntegrity()
         {
             var key = OtpCalculationTests.RfcTestKey;
             CollectionAssert.AreEqual(OtpCalculationTests.RfcTestKey, key);
         }
 
-        [TestMethod]
+        [Test]
         public void TotpUtcOverload()
         {
             var totp = new Totp(OtpCalculationTests.RfcTestKey);
             Assert.AreEqual(code1, code2);
         }
 
-        [TestMethod]
+        [Test]
         public void TotpRemainingTimeUtcOverload()
         {
             var totp = new Totp(OtpCalculationTests.RfcTestKey);

File OtpSharp.Tests/UrlTests.cs

 using Base32;
 using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
+using NUnit.Framework;
 using System;
 using System.Collections.Specialized;
 
 namespace OtpSharp.Tests
 {
-    [TestClass]
+    [TestFixture]
     public class UrlTests
     {
         #region to url
 
-        [TestMethod]
+        [Test]
         public void TotpUrl()
         {
             var url = KeyUrl.GetTotpUrl(OtpCalculationTests.RfcTestKey, "user");
             Assert.AreEqual(string.Format("otpauth://totp/user?secret={0}", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey)), url);
         }
 
-        [TestMethod]
+        [Test]
         public void TotpUrl_Sha256()
         {
             var url = KeyUrl.GetTotpUrl(OtpCalculationTests.RfcTestKey, "user", mode: OtpHashMode.Sha256);
             Assert.AreEqual(string.Format("otpauth://totp/user?secret={0}&algorithm=Sha256", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey)), url);
         }
 
-        [TestMethod]
+        [Test]
         public void TotpUrl_Sha512()
         {
             var url = KeyUrl.GetTotpUrl(OtpCalculationTests.RfcTestKey, "user", mode: OtpHashMode.Sha512);
             Assert.AreEqual(string.Format("otpauth://totp/user?secret={0}&algorithm=Sha512", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey)), url);
         }
 
-        [TestMethod]
+        [Test]
         public void TotpUrl_StepSizeFifteen()
         {
             var url = KeyUrl.GetTotpUrl(OtpCalculationTests.RfcTestKey, "user", step: 15);
             Assert.AreEqual(string.Format("otpauth://totp/user?secret={0}&period=15", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey)), url);
         }
 
-        [TestMethod]
+        [Test]
         public void TotpUrl_DigitsEight()
         {
             var url = KeyUrl.GetTotpUrl(OtpCalculationTests.RfcTestKey, "user", totpSize: 8);
             Assert.AreEqual(string.Format("otpauth://totp/user?secret={0}&digits=8", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey)), url);
         }
 
-        [TestMethod]
+        [Test]
         public void TotpUrl_DigitsTen()
         {
             new Action(() => KeyUrl.GetTotpUrl(OtpCalculationTests.RfcTestKey, "user", totpSize: 10))
                 .WithMessage("size must be 6 or 8");
         }
 
-        [TestMethod]
+        [Test]
         public void TotpUrl_Sha512AndStepSizeFifteen()
         {
             var url = KeyUrl.GetTotpUrl(OtpCalculationTests.RfcTestKey, "user", step: 15, mode: OtpHashMode.Sha512);
             Assert.AreEqual(string.Format("otpauth://totp/user?secret={0}&algorithm=Sha512&period=15", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey)), url);
         }
 
-        [TestMethod]
+        [Test]
         public void TotpUrl_Sha512AndStepSizeFifteenDigitsEight()
         {
             var url = KeyUrl.GetTotpUrl(OtpCalculationTests.RfcTestKey, "user", step: 15, mode: OtpHashMode.Sha512, totpSize: 8);
             Assert.AreEqual(string.Format("otpauth://totp/user?secret={0}&digits=8&algorithm=Sha512&period=15", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey)), url);
         }
 
-        [TestMethod]
+        [Test]
         public void TotpUrl_EmptyUser()
         {
             new Action(() => KeyUrl.GetTotpUrl(OtpCalculationTests.RfcTestKey, string.Empty))
                 .WithMessage("Value cannot be null.\r\nParameter name: user");
         }
 
-        [TestMethod]
+        [Test]
         public void TotpUrl_NullUser()
         {
             new Action(() => KeyUrl.GetTotpUrl(OtpCalculationTests.RfcTestKey, null))
                 .WithMessage("Value cannot be null.\r\nParameter name: user");
         }
 
-        [TestMethod]
+        [Test]
         public void TotpUrl_NullKey()
         {
             new Action(() => KeyUrl.GetTotpUrl(null, "user"))
                 .WithMessage("Value cannot be null.\r\nParameter name: key");
         }
 
-        [TestMethod]
+        [Test]
         public void TotpUrl_EmptyKey()
         {
             new Action(() => KeyUrl.GetTotpUrl(new byte[] { }, "user"))
                 .WithMessage("Value cannot be null.\r\nParameter name: key");
         }
 
-        [TestMethod]
+        [Test]
         public void HotpUrl()
         {
             var url = KeyUrl.GetHotpUrl(OtpCalculationTests.RfcTestKey, "user", 1);
             Assert.AreEqual(string.Format("otpauth://hotp/user?secret={0}&counter=1", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey)), url);
         }
 
-        [TestMethod]
+        [Test]
         public void HotpUrl_2()
         {
             var url = KeyUrl.GetHotpUrl(OtpCalculationTests.RfcTestKey, "user", 2);
             Assert.AreEqual(string.Format("otpauth://hotp/user?secret={0}&counter=2", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey)), url);
         }
 
-        [TestMethod]
+        [Test]
         public void HotpUrl_Digits8()
         {
             var url = KeyUrl.GetHotpUrl(OtpCalculationTests.RfcTestKey, "user", 2, 8);
             Assert.AreEqual(string.Format("otpauth://hotp/user?secret={0}&digits=8&counter=2", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey)), url);
         }
 
-        [TestMethod]
+        [Test]
         public void HotpUrl_DigitsTen()
         {
             new Action(() => KeyUrl.GetHotpUrl(OtpCalculationTests.RfcTestKey, "user", 1, 10))
 
         #region from URL
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl()
         {
             var url = string.Format("otpauth://totp/user?secret={0}", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             Assert.AreEqual(OtpHashMode.Sha1, totp.GetHashMode(), "Hash mode doesn't match");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_ExplicitStep()
         {
             var url = string.Format("otpauth://totp/user?secret={0}&period=30", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             Assert.AreEqual(OtpHashMode.Sha1, totp.GetHashMode(), "Hash mode doesn't match");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_StepInvalid()
         {
             var url = string.Format("otpauth://totp/user?secret={0}&period=a", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             new Action(() => KeyUrl.FromUrl(url)).ShouldThrow<ArgumentException>().WithMessage("Invalid digits , must be a number");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_NegativeStep()
         {
             var url = string.Format("otpauth://totp/user?secret={0}&period=-1", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             new Action(() => KeyUrl.FromUrl(url)).ShouldThrow<ArgumentException>().WithMessage("Invalid Period -1, must be at least 1");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_ZeroStep()
         {
             var url = string.Format("otpauth://totp/user?secret={0}&period=0", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             new Action(() => KeyUrl.FromUrl(url)).ShouldThrow<ArgumentException>().WithMessage("Invalid Period 0, must be at least 1");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_ExplicitHashMode()
         {
             var url = string.Format("otpauth://totp/user?secret={0}&algorithm=Sha1", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             Assert.AreEqual(OtpHashMode.Sha1, totp.GetHashMode(), "Hash mode doesn't match");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_ExplicitHashModeInvalid()
         {
             var url = string.Format("otpauth://totp/user?secret={0}&algorithm=Garbage", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             new Action(() => KeyUrl.FromUrl(url)).ShouldThrow<ArgumentException>().WithMessage("Invalid Algorithm Garbage");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_Sha256()
         {
             var url = string.Format("otpauth://totp/user?secret={0}&algorithm=Sha256", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             Assert.AreEqual(OtpHashMode.Sha256, totp.GetHashMode(), "Hash mode doesn't match");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_Sha512()
         {
             var url = string.Format("otpauth://totp/user?secret={0}&algorithm=Sha512", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             Assert.AreEqual(OtpHashMode.Sha512, totp.GetHashMode(), "Hash mode doesn't match");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_StepSizeFifteen()
         {
             var url = string.Format("otpauth://totp/user?secret={0}&period=15", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             Assert.AreEqual(OtpHashMode.Sha1, totp.GetHashMode(), "Hash mode doesn't match");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_DigitsEight()
         {
             var url = string.Format("otpauth://totp/user?secret={0}&digits=8", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             Assert.AreEqual(OtpHashMode.Sha1, totp.GetHashMode(), "Hash mode doesn't match");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_DigitsTen()
         {
             var url = string.Format("otpauth://totp/user?secret={0}&digits=10", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             new Action(() => KeyUrl.FromUrl(url)).ShouldThrow<ArgumentException>().WithMessage("Invalid Digits 10, must be 6 or 8");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_DigitsInvalid()
         {
             var url = string.Format("otpauth://totp/user?secret={0}&digits=a", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             new Action(() => KeyUrl.FromUrl(url)).ShouldThrow<ArgumentException>().WithMessage("Invalid digits a, must be a number");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_Sha512AndStepSizeFifteen()
         {
             var url = string.Format("otpauth://totp/user/?secret={0}&algorithm=Sha512&period=15", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             Assert.AreEqual(OtpHashMode.Sha512, totp.GetHashMode(), "Hash mode doesn't match");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_Sha512AndStepSizeFifteenInverseOrder()
         {
             var url = string.Format("otpauth://totp/user?secret={0}&period=15&algorithm=Sha512", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             Assert.AreEqual(OtpHashMode.Sha512, totp.GetHashMode(), "Hash mode doesn't match");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_Sha512AndStepSizeFifteenDigitsEight()
         {
             var url = string.Format("otpauth://totp/user/?secret={0}&algorithm=Sha512&period=15&digits=8", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             Assert.AreEqual(OtpHashMode.Sha512, totp.GetHashMode(), "Hash mode doesn't match");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_EmptyUrl()
         {
             new Action(() => KeyUrl.FromUrl(string.Empty)).ShouldThrow<ArgumentNullException>().WithMessage("Value cannot be null.\r\nParameter name: rawUrl");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_NullUrl()
         {
             new Action(() => KeyUrl.FromUrl(null)).ShouldThrow<ArgumentNullException>().WithMessage("Value cannot be null.\r\nParameter name: rawUrl");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_InvalidQueryString()
         {
             var url = string.Format("otpauth://totp/user?secret={0}&algorithm=Sha512&period=15&digits=8&blah=b", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             new Action(() => KeyUrl.FromUrl(url)).ShouldThrow<ArgumentException>().WithMessage("Invalid parameter in query string");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_MalFormattedUrl_NoUser()
         {
             var url = string.Format("otpauth://totp?secret={0}&algorithm=Sha512&period=15&digits=8", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             new Action(() => KeyUrl.FromUrl(url)).ShouldThrow<ArgumentException>().WithMessage("rawUrl is invalid");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_MalFormattedUrl_NoUserWithSlash()
         {
             var url = string.Format("otpauth://totp/?secret={0}&algorithm=Sha512&period=15&digits=8", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             new Action(() => KeyUrl.FromUrl(url)).ShouldThrow<ArgumentException>().WithMessage("rawUrl is invalid");
         }
 
-        /// <summary>
-        /// not yet implemented
-        /// </summary>
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_MalFormattedUrl_ExtraArgument()
         {
             var url = string.Format("otpauth://totp/user/extra?secret={0}&algorithm=Sha512&period=15&digits=8", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             new Action(() => KeyUrl.FromUrl(url)).ShouldThrow<ArgumentException>().WithMessage("rawUrl is invalid");
         }
-        /// <summary>
-        /// not yet implemented
-        /// </summary>
-        [TestMethod]
+
+        [Test]
         public void FromTotpUrl_MalFormattedUrl_ExtraArgumentWithSlash()
         {
             var url = string.Format("otpauth://totp/user/extra/?secret={0}&algorithm=Sha512&period=15&digits=8", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             new Action(() => KeyUrl.FromUrl(url)).ShouldThrow<ArgumentException>().WithMessage("rawUrl is invalid");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_InvalidScheme()
         {
             var url = string.Format("otp://totp/user?secret={0}&algorithm=Sha512&period=15&digits=8", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             new Action(() => KeyUrl.FromUrl(url)).ShouldThrow<ArgumentException>().WithMessage("invalid scheme otp. Must be otpauth://");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_NoSecret()
         {
             var url = "otpauth://totp/user?period=30";
             new Action(() => KeyUrl.FromUrl(url)).ShouldThrow<ArgumentException>().WithMessage("must contain secret");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_NoQueryString()
         {
             var url = "otpauth://totp/user";
             new Action(() => KeyUrl.FromUrl(url)).ShouldThrow<ArgumentException>().WithMessage("Must have a query string");
         }
 
-        [TestMethod]
+        [Test]
         public void FromTotpUrl_WithCounter()
         {
             var url = string.Format("otpauth://totp/user?secret={0}&counter=1", Base32Encoder.Encode(OtpCalculationTests.RfcTestKey));
             new Action(() => KeyUrl.FromUrl(url)).ShouldThrow<ArgumentException>().WithMessage("Invalid parameter in query string");
         }
 
-        [TestMethod]