Why would anyone use MSTest over NUnit?

Posted: 20th September 2011 by Drew Peterson in DNK Jump In

Choices, choices, choices. The advantage of having a thriving open-source community in the .Net world is that you have choices…the disadvantage is that you have to actually make them. Selecting a unit-testing framework is an important step, and can have far-reaching effects across your organization and over the lifetime of your products. Complicating things further, you must also decide whether you want to trust an open-source solution, or go with what Microsoft offers out-of-the-box. Given that Microsoft only provides one solution for unit testing, MSTest is our candidate there. In the open-source world, NUnit is the incumbent candidate.

MSTest’s greatest strength is in who created it. Microsoft’s offering of a complete end-to-end solution for product development, testing, deployment, and source control is a boon to developers. Writing applications in .Net means paying the Microsoft tax up-front, so why not keep it all integrated in the same product suite and offer developers a superior experience? Getting up and running in MSTest is as simple as Add -> New Test Project. No other solution provides that level of simplicity, and no other solution can guarantee that they can support future versions of the .Net runtime and Visual Studio.

I don’t feel that one killer feature, or one strength, should be enough to sway anyone on such an important choice. This is especially so when some would argue that other choices like NUnit are the defacto solution. So what are MSTest’s strengths? Why should I pick it over NUnit? Let’s jump in and find out!

Drew: MSTest properly instantiates a new instance of the test class for each test method being executed. This provides a number of advantages. First, it allows for easy state management in your tests, your setup and teardown code will be run each time a method is called and your instance variables are automatically reset. There’s no need to reset them manually as it is in NUnit. Indeed, many of MSTest’s other strengths rely on this very principle, as we shall see.

MSTest is fully multithreaded. Each test runs on its own thread, and is completely isolated from other test methods being executed. If you need to rely on state provided by another test, as we’ll get into next, it’s no problem as you can also specify the order the tests are executed in. Again, this all goes back to MSTest doing the correct thing and instantiating a new test class for each test method that is executed.

At this point, some of MSTest’s detractors will point out that instantiating a new instance of the test class makes it difficult to work with test data, or rely on the state of some external object after the execution of a previous test method. I’m glad they did, because it will allow me to explain the benefits of the TestContext class.

The TestContext class is an abstract class which is part of MSTest. The TestContext class can store various bits of information about a test such as performance metrics, test outcome, test name, arbitrary data contained within a Dictionary object, as well as advanced information such as a DbConnection and DataRow. By passing along this information via a known interface (the TextContext abstract class), we get the best of both worlds. Isolated by default, and shared-state when we want.

Performance testing can be done by taking advantage of the timer properties of the TestContext class. This would even allow you to fail tests if timers exceeds a certain threshold.

By utilizing the DbConnection and DataRow properties of the TestContext class, we can build data-driven tests in MSTest. By using the correct MSTest attributes on our test method, we can specify that a test method run over each row from a table, view, or stored procedure. This allows us to not only test the logic in our database layer, but also that stored procedures are returning the expected output, but not at the same time of course. It’s important to remember to test as little as possible in a single test method. Regardless, the opportunity to test database logic along with your application logic exists. If we were to set up some test data in our test class setup, we could work with that test data in our test methods, and clean it all up in our teardown method when we’re done. But what if you want to share that test data between multiple test methods and not tear it down between each method? MSTest has an answer for that! In MSTest you can create setup and teardown methods for an entire assembly, meaning you can group multiple tests and test classes together into one assembly and work with the same data.

MSTest also integrates with Team System, which means you can get all sorts of fancy reports on your unit tests for free. What’s better, you can design custom reports based on performance metrics, certain test groups, whatever your heart desires. If you haven’t seen the kinds of reports that Team System can churn out, go take a look. They are impressive.

There are a few advanced tools that go hand-in-hand with MSTest, such as Pex, but it’s difficult to compare with other options once you start including all the extra tools built around the test framework.

Vijay:

NUnit is a unit-testing framework for all .Net languages. NUnit is written in C#. The best thing about NUnit is that it is open-source. This means that all of NUnit source is available for download. The source can be extended or customized according to the needs of your organization.

NUnit is free. However, the free edition of NUnit does not integrate well with Visual Studio. TestDriven.Net ensures that NUnit is well integrated with Visual Studio. A single license of TestDriven.Net costs about $160. In addition to supporting NUnit, TestDriven.Net supports other unit-testing frameworks like MbUnit, NCover, Reflector, TypeMock.

NUnit appeals more to the developers than the testers. Here is why. NUnit 2.4 introduces a constraint-based assert framework. Using the constraint-based assert framework, the code becomes very readable. For example, the syntax for asserting if an object is not null is as simple as: Assert.That(obj, Is.Not.Null).

There are many more examples of readable asserts. The following table shows this:

Code Explanation
Assert.That(collection, Is.Unique) Asserts that the collection is composed of unique elements.
AssertThat(number, Is.AtMost(100)) Asserts that the number is lesser than or equal to 100.
Assert.That(number, Is.TypeOf(typeof(int)) Asserts that number is of integer type.
Assert.That(collection, Is.All.GreaterThan(0)) Asserts that all items in the collection is greater than 0.
Assert.That(collection, Has.Some.GreaterThan(90)) Asserts that the collection has some numbers greater than 90.
Assert.That(fruits, Has.Member(“Apple”)) Asserts that the fruits collection has the fruit  – “Apple”

Another advantage of using NUnit is that it supports a lot of attributes. There are a lot of attributes that support providing input values to a test. As you know, a test can contain multiple input parameters. The TestCase attribute can be used to supply values to each input parameter. The TestCase attribute also has a named property called Result which is used to verify the value returned after executing the test. Consider a test method with two input parameters a, b as follows:

[Test, Combinatorial]
public void Add ([Values(1,2)] int a, [Values(3,4)] int b)
{
}

The above test is run four times with the following input parameters (a,b): (1,3), (1,4), (2,3), (2,4). NUnit also has a Sequential attribute. If the previous test is decorated with a Sequential attribute instead of a combinatorial attribute, the test method will be run two times with the following input parameters: (1,3), (2,4).

Input parameters can be decorated by a Random attribute. Using the Random attribute supplies a random value to the input parameter within a specific range. Alternatively, the input parameter can be decorated with a Range attribute. A Range attribute [Range(4,10,2)] provides the same input values as a Values attribute specified by [Values(4,6,8,10)]. The Range attribute can be used to run the test with a lot of input parameters to ensure that the tests run well under many circumstances. As you can see, NUnit is a good unit testing framework for systems that involve a lot of mathematical operations.

Sometimes, not all test cases need to be run. The Ignore attribute ensures that the tests decorated with the attribute will not be run. NUnit also has an Explicit attribute. Tests decorated with an Explicit attribute will not run unless specifically invoked from the GUI. The Category attribute categorizes tests. This allows tests specific to a category to be run. There is also another way that a tester can execute a set of tests. This is done with the help of the Suite attribute. The Suite attribute is more helpful for running automated tests using the command-line interface. This is especially useful if you want to run a set of tests after doing the build.

A test fixture can be decorated with a Culture attribute. Providing a value for the Culture attribute ensures that the set of tests within a test fixture is executed only for the specified culture. If the culture is set to fr-Fr, then the tests within the test fixture is run only when the current culture is french. Sometimes, it is required to run tests under a specific culture. To change the culture of the current thread in which the tests are running, NUnit provides two attributes – SetCulture and SetUICulture.

As you can see, NUnit is very appealing to developers who write the automated tests. NUnit provides an easy-to-code constraint-based assert framework. It also has a wide variety of attributes, especially attributes that set the input values to the tests. These developer-friendly features make NUnit a good alternative to MSTest.

  • Drew Peterson

    It’s unfortunate that an open-source solution requires a $160 investment to be useful. ;-)
    Using the freely available NUnit test runner, there’s no ability to integrate testing with the IDE correct? And no ability to go to the failing test directly from the test output?

  • Drew Peterson

    If I may pick on your points a little more Vijay, I’d like to point out one instance where NUnit isn’t very friendly to the developer: http://blogs.msdn.com/b/jamesnewkirk/archive/2004/12/04/275172.aspx . In this instance, the developer must fight with NUnit as it does not create a new instance of the test fixture each time a test method is executed. James Newkirk, one of NUnit 2.0′s authors, even admits it was a mistake.

  • Vijay T

    As James admits, it is not a good design choice. This ignores the concept of test isolation. But, the design choice was made for a reason. If multiple tests uses a database connection, it makes sense to use the same TestFixture. NUnit supports a TestFixtureSetup method to do costly initializations. It also supports TestFixtureTeardown method to dispose the costly objects. To ensure that the TestFixture retains the original state, we have two methods – Setup and Teardown, that are run before each test method is executed. Once, a developer understands how NUnit works, it is easier to code.

  • Vijay T

    NUnit works well without TestDriven.Net. The $160 investment makes your life easier. Compare this to the Visual Studio Test Professional Edition that costs close to $900.

  • Vijay T

    Here is a link that compares the four testing frameworks – NUnit, MSTest, MbUnit, xUnit: http://www.mtelligent.com/journal/2008/7/1/automated-testing-with-nunit-mstest-mbunit-and-xunitnet.html

    According to the author, there is no compelling reason to move to MSTest, if you are using NUnit. I agree with the author that MSTest attributes are less intuitive and harder to understand than NUnit. MSTest also relies extensively on the database for setting up the test parameters.

  • http://www.alvinashcraft.com/2011/09/21/dew-drop-september-21-2011/ Dew Drop – September 21, 2011 | Alvin Ashcraft's Morning Dew

    [...] Why would anyone use MSTest over NUnit? (Drew Peterson) [...]

  • Drew Peterson

    Actually, that version isn’t required to get the testing features required for day-to-day work. Here’s a link showing what testing features are available in the Professional edition of Visual Studio vs what’s only available in the Team System version: http://msdn.microsoft.com/en-us/library/bb385902(v=vs.90).aspx

  • Drew Peterson

    Could you expand on what you mean by relying on the database for test parameters? As for the article, I think I would even agree that it doesn’t make sense to switch frameworks. However, I would say that based on the strengths of MSTest that I’ve outlined, it’s a solid choice when you’re picking what unit testing framework you’d like to use.

  • Drew Peterson

    Could you expand on what you mean by relying on the database for test parameters? As for the article, I think I would even agree that it doesn’t make sense to switch frameworks. However, I would say that based on the strengths of MSTest that I’ve outlined, it’s a solid choice when you’re picking what unit testing framework you’d like to use.

  • http://twitter.com/AdamSmithTech Adam Smith

    ReSharper has a test runner feature that supports running NUnit tests (and other test framework tests) directly in the VS interface. It is about $199 for a single personal licence but the additional features it supplies are more than worth the asking price… If you are not using it you should be – once learnt you will be alot quicker writing code. http://www.jetbrains.com/resharper/

  • Anonymous

    The only reason to use MSTest is if your point haired boss makes you due to a “we only use Microsoft” or “Open Source is Evil” mentality.

  • J E Young

    Database and unit tests in the same sentence: not good. Argument discarded.

  • Drew Peterson

    Very true, it’s definitely that way where I work.

  • Drew Peterson

    But pointing out ReSharper is like cheating, everyone loves it ;-)

  • Drew Peterson

    If you were just starting out and hadn’t yet settled on a unit testing framework, what would you think about the coverage and testing reports out of Team System?

  • Drew Peterson

    I didn’t even get into covering Pex for generating unit test code in my points, but perhaps I should have. It’s another feature that I think makes MSTest easier on developers.

  • Drew Peterson

    Actually, it *is* possible to run them without Visual Studio if you desire: http://www.shunra.com/shunrablog/index.php/2009/04/23/running-mstest-without-visual-studio/ I’m not going to go so far as to say that’s easy, but it is an option. When you’re considering how much of an improvement for the developer MSTest is, I’ll cut it a little slack on the CI side. Maybe others won’t ;-)

  • Drew Peterson

    But what if they have a compelling reason other than “we only use Microsoft”? MSTest really shines when it comes to data-driven tests, I’m not sure if you work with heavily data-driven applications but making testing with data easier is a big +1 in my book.

  • Drew Peterson

    You’ve discarded the entire argument because of that? How do you go about testing your database layer? Manually?

  • Vijay T

    MSTest definitely makes it easier for developers to create test methods. It is a little bit work to review each test method and correct the Asserts.

    In a true TDD environment, developers write the test case, then write the code, till the test passes.

    The other problem with MSTest is to setup the test data.

    Any serious product that is being developed today requires automated unit tests. Many developers may be working on legacy systems that are just being maintained.

  • Vijay T

    TFS 2010 can be used to setup continuous integration builds. By customizing the build template, it is possible to run NUnit tests. Here is a post that describes how to do it: http://blog.gfader.com/2011/06/running-nunit-tests-in-tfs-2010.html

  • http://blog.robertgreyling.com RobertTheGrey

    One of my biggest issues with MSTest is how it handles the testing of exceptions. xUnit was the first to put an Assert.Throws syntax in so that you could at least continue with any further test workflow you might need to and doesn’t just drop you out of the test right there.

    MSTest still uses the archiac [ExpectedException] attribute and your test dies as soon as it throws. Even NUnit has fixed this flaw in how exceptions are tested for.

    In addition, some would argue that specifying or needing to specify the order of your tests is a code smell and you should rather be fixing your code. Every test should be able to run independently of another and I know MSTest allows for this, but I don’t see how it can be described as a plus to be able to order your tests.

    I think you have a good point with Data Driven tests, but I must say that I try my best not to have to go there. The test suites get slow and over time costs plenty of developer hours just waiting for the build to go green. Quick and dependency free tests are the surest way to get developers to run them frequently

    Rob

  • Vijay T

    NUnit has a TestCase attribute that supplies values to input parameters and the result expected after running the test. I do not think MSTest has an equivalent of the TestCase attribute.

  • http://www.clear-lines.com/blog Mathias

    I believe Pex works with NUnit as well, and is not specific to MSTest.

  • http://www.clear-lines.com/blog/ Mathias Brandewinder

    Depends what data driven tests you are talking about. IMO, the way MSTest handles test data with separate files containing your sample inputs is horrendous; by contrast, a feature like TestCase in NUnit (or Theory in xUnit) is very convenient: you define your entire test in code, everything is in one place.

  • http://profiles.google.com/talktopete Pete Weissbrod

    I attempted to give MSTest a chance in one of my SharePoint projects. By default I was getting strange error messages until I discovered that I must force MSTest to run in a 64 bit mode through a config file. I agree with the poster above that MS test really gives no compelling value over NUnit.

    And the argument over a $160 plugin? Are you serious? What a short-sighted argument, this tool will pay itself off in less than a week in my job.

  • Drew Peterson

    Ok I understand what you’re saying now. It is possible to do something similar using a CSV or XML datasource, but it’s not as succinct as the TestCase attribute method that MBUnit and NUnit provide.

  • Drew Peterson

    You’re right, I wasn’t aware of that.

  • Drew Peterson

    That’s a good point, but I was referring to tests driven off staging or generated data from a database. I wish that MSTest had something similar to TestCase.

  • Drew Peterson

    It wasn’t an argument, just a cheeky jab.

  • Drew Peterson

    One option to alleviate the possible slowness in testing with values from the database is to separate those tests into a separate test project, only to be run when necessary.

  • Anonymous

    Vijay, saying that being open source is NUnit’s biggest advantage may be true, from an ecosystem perspective, but it’s not a very compelling argument to say that it has anything to do with the possibility to extend and modify the core. It’s just not something that ever happens.

    It is quite astonishing that no good, free or open source VS integration exists for NUnit. It’s the de facto standard, but TestDriven/ReSharper is always presented as the solution. They are definitely worth their cost, but can still be a hard sell in a MS-centric organisation. There are free alternatives, they’re just not very good. Yet.

    Gallio’s (MBunit) VS integration can make VS think that NUnit is MSTest, but there are a few bugs.

    Other than that, I so prefer NUnit to MSTest. The syntactical deficiencies of MSTest can be overcome, but it’s also significantly slower, has a messy execution/shadow copy model and the idea that private members should be accessed is a road to disaster (a road that of course can be avoided).

    The Setup/Teardown model in NUnit may be inconvenient at times, but it’s also very easy and predictable.

  • http://www.Marisic.Net dotnetchris

    I use MSTest just because it’s baked into Visual Studio fully. It is somewhat clunky especially the way it requires the static methods for the classinitialize/classteardown even those attribute names themselves are pretty clunky and hard to remember. Other problems it has is making a base test class to make it easier to have stuff ready to go for some things. It gets the job done however.

    The other prime feature is the baked in code coverage / analysis tools in visual studio.

  • http://twitter.com/debug_mode dhananjay kumar

    Thank you so much for grear article. As of me I never used NUnit and I prefer Telerik Just Code [ Just Mock ] for the Visual Studio integrated testing. I feel its awesome tool given by Telerik to us. Just Mock helps us to do Superior Unit Testing, Reduced Development Times,Arrange, Act, Assert ,Mock Everything,Fast Database Testing,Unobtrusive Mocking,Error-free Mocking,Dual Architecture,Integration with Other Tools. Though it is not open source but worth a try for better integrated testing .

  • http://www.facebook.com/kodefuguru Christopher Brian Eargle

    Full Disclosure: I work for Telerik. JustCode has a built in unit test runner that works with NUnit (as well as MsTest, MSpec, MBUnit and xUnit). There is a free edition of JustMock available.

  • Ben Linville

    I have found that MS Test works great. If you test privates, thats your own bad… we cant protect from stupidity. At my office we have a TFS thing going on… it replaced CC and SVN. While it has some of its own issues, the testing integration for our QA department is AWSOME. If you are lame and dont want to customize the workflows for TFS, you will have problems. But then I spend just as much time doing that as managing CC configs and NAnt build files.

  • Anonymous

    Which is where TeamCity comes into the picture. We switched from TFS2010 to TeamCity about a year ago, and it’s superb! I won’t dispute that a fully customized Team System setup could be a good thing, but it takes a lot of work and for us it was not worth it.

  • Kangkan Goswami

    My viewpoint is not looking at TDD. I shared my experience involves working with teams that are not following TDD and so follow the old school of thought and generate the design on a modelling tool and forward engineer to generate the code, and start building in the features. The teams use to do the unit testing later when they build up some testable features.

    So, at this point, most of the developers (due to the delivery pressure and attitude issues) start testing the code in adhoc manner by looking at functionality (similar to black box testing).

    MSTest gave the easy smooth transition for the start.

  • http://profiles.google.com/david.l.finley David Finley

    Speak for yourself. It is almost impossible here to get corporate to buy MSDN for developers. I have had to buy it personally, out of my own funds.

  • Thomas Weller

    Hi,

    I’m somewhat astonished about the fact that nobody so far addressed an issue which is absolutely critical to the profession of software development as a whole: productivity. This is the area where MSTest dramatically falls behind a decent development environment with an open xUnit testing framework like NUnit and a test runner like ReSharper or TestDriven.Net. Everything else is just the technical details which are simply not relevant to non-developers!

    - Preliminary note: I’m a user of MbUnit/Gallio, NUnit, and R# for many years. I started writing tests long before Microsoft had the idea of making their own testing framework. I also did some projects with MSTest and TFS nowadays (because circumstances forced me to do so, see e.g. here: http://www.slideshare.net/th-weller/introduction-to-testing-with-mstest-visual-studio-and-team-foundation-server-2010). -

    When it comes to MSTest, there’s one sentence from Roy Osherove in a post to the very same issue (‘Why MSTest is the IE6 of unit test frameworks’, http://osherove.com/blog/2011/8/24/why-mstest-is-the-ie6-of-unit-test-frameworks.html) which always makes me laugh:
    “MSTest continues to be the fat, whiney kid in class, where the only reason he has to be in that school is because his father donated a library to it.”
    I think this hits the nail exactly on the head…

    Seriously, these are the main reasons why I consider MSTest a bad choice:

    * MSTest is in-ergonomic
    An MSTest test requires the developer to perform an extra double-click to open a new window to see the test results details. This new window obfuscates my real code and also has to be closed afterwards. Sounds a bit silly and over the top? Well, if you seriously do TDD, you will have to perform these steps dozens or even hundreds of times per day – and then it soon gets annoying, because it hinders your workflow. With NUnit and R# in contrary, you see your test results in a VS tool window side by side with your code.

    * MSTest is inflexible
    The above article describes in some detail, how flexible NUnit is through its many attributes. There are far more than in MSTest. I should add: There are also much more different Asserts in NUnit. Together, this makes NUnit a great deal more flexible – with NUnit, there are far fewer occasions where you encounter a real-life scenario, which cannot be reproduced by your testing framework. Especially data-driven testing is a pain with MSTest – this alone would be enough for me to throw it away…

    * It’s nearly impossible to extend MSTest
    With Open Source Frameworks like NUnit, it’s usually quite easy to write extensions, custom attributes, plugins and the like. This is because you can always look in the code to see what’s happening, and because frameworks like NUnit are intentionally designed to be extended by the user, which means that there are dozens of possible extension points built in to the framework. Nothing of that is true for MSTest.
    (Some weeks ago, a customer had the requirement to write UI tests against different browsers. He wanted this to be controlled via simple attributes on the test methods. While this would have been a half-day task with NUnit, I needed to do it with MSTest. Man! It took me four long days and hundreds of lines of quite esoteric and unmaintainable boilerplate code. And I did not even do the UI integration part! That’s what I really call ‘Burning money’…)

    From a developer’s perspective, there are many reasons why you would prefer NUnit over MSTest, and there also might be some reasons for MSTest, as outlined in the article. But the bottom line is: You get more done in fewer time when _NOT_ using MSTest for your tests. And that’s what we’re paid for in the end. No one (except a fellow programmer) in the end is interested in _how_ you do it. The only question is how much work you get done in a certain amount of time…

    But apart from the discussion about technical details: There’s no need to make a decision – the Gallio framework can run all test frameworks in parallel…

  • Drew Peterson

    Wow, that’s a lot to chew on! First off, thanks for taking the time to give us such an in-depth response. It really makes us feel good that our article has brought about so much discussion and participation.

    You bring up some good points, and I can’t find fault with your arguments. I did not consider discussing the non-technical advantages/disadvantages of MSTest at all, and I feel like perhaps I did miss the most important point in not doing so. On the topic of productivity, I feel like I may have to concede.

    Well played :-)

  • Martin Moe

    It’s not actually cheating, just showing of ignorance. ReSharper supports both NUnit and MSTest based tests ;-)

  • Thomas Weller

    ups – Please just ignore this

  • Thomas Weller

    Hi Drew,

    thanks for the kind words.

    I had this discussion a few times with my customers in the not-so-far past (I’m a freelancer, so they are changing every few months). They (non-technical business people, not the developers themselves) insisted on using Microsoft products, because ‘hey, it’s from MS, so it must be great’ (sigh…). That’s why I had the arguments relatively fresh in mind, and that’s why I’m trying to argue a bit from the non-technical, business side of things.

    The sad thing is that you are the only one so far who fully agrees ;-)…

  • polyglot dev guy

    suprised that noone has mentioned speed. the last project i worked on was pretty big – we had a good 10000 unit tests, plus another 500 or so integration and acceptance tests. the project initially started out with mstest, but build and test time became so long that we changed to nunit and never looked back.

    mstest is so unbelievably slow that proper TDD and (perhaps more importantly for big teams) proper CI was simply impossible – noone is going to stick around 45 minutes to see if their checkin has broken some obscure feature somewhere!

    with nunit that 45 minutes was brought down to just on 10 – still not ideal, but with some clever rake tasks and good team city setup the CI process became smooth enough that rapid feedback became a reality.

    oh and the point about team system integration is imo irrelevant – team system seldom makes anyone except waterfall project managers happy :(

  • Vijay T

    Thanks for your feedback on NUnit’s superior performance. I could not find a decent whitepaper comparing the performance of the various Unit testing frameworks.

  • Anonymous

    I think saying NUnit’s performance is “superior” is circumstancial.

    Keep in mind NUnit is a stand-alone product, in a stand-alone UI – it is built for running tests, and that’s exactly what it does, and it does it exceptionally well.

    Visual Studio and MSTest on the other hand is the kitchen sink – a one stop shop – there is a lot going on in that IDE, including running tests.

    Mike Hanson published a blog post doing an investigation into test running performance metrics. He determined that performance issues are not necessarily attributed to the test framework of choice, but rather the test runner.

    You can see from his results, that MSTest *can* perform about as well as NUnit. http://www.mikehanson.com/post/MSTest-vs-NUnit-Run-Times.aspx

  • Anonymous

    Have you used Fluent Assertions with MSTest ? I haven’t felt restricted in the least, IMO

  • http://www.thomas-weller.de Thomas Weller

    It’s not about feeling restricted in the strict sense. It’s more about the overall impression of productivity and flexibility. NUnit simply has far more options to do even quite complicated and esoteric things.
    It’s certainly true that MSTest gets the job done – somehow. But NUnit usually gets it done faster, more efficient and more elegant.