DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report

Using Approval Testing for ELMAH.MVC Project

Alexander Beletsky user avatar by
Alexander Beletsky
·
Jun. 16, 12 · Interview
Like (0)
Save
Tweet
Share
5.29K Views

Join the DZone community and get the full member experience.

Join For Free
During the ELMAH.MVC 2.0 preparation I had a bit challenging task. As I mentioned, I was about to adopt some code from ELMAH.Sandox project. The 2.0 release included some new features, but what was important to me is make sure I keep previous ELMAH.MVC functionality.

In case you are following my blog, you probably read about Approval.Test framework, which I personally like and recommend to my fellow developers. I did some posts, there I tried to show some Approvals benefits. Today, I'll show some real-life use case.

Installing by NuGet

Last time I played with Approvals, the binaries were only available at SourseForge project page. It is not convenient at all. I was happy to see the tweet from Llewellyn Falco, he mentioned that ApprovalTests are now available on NuGet. So, installation now as easy as:

PM> Install-Package ApprovalTests

Thinking of test

I had to have some kind of assurance, that I will not break existing ELMAH pages after I switch to new ELMAH controller. Basically, I need to have some 'Master Database' that would contain all logged errors and I need to grab all possible output that is being generated by ELMAH error log page handler.

This is what perfectly match the 'Locking Down' testing strategy. In locking down testing, you try to get all possible system output, and approve it. In my case, I wanted to approve that all HTTP calls to ELMAH pages, like '/elmah', '/elmah/stylesheet', '/elmah/rss' and so on, still work as they worked before, meaning producing the same output as they produced before.

Test implementation

For my 'do' step of the the test, I need to collect all possible applications output. I already know all URL's, so I just fired up the site with ELMAH.MVC 1.3.2 version installed. I configured the site to use XML files for storing the tests, so I can easily copy them before each test run. That made a kind of 'Master Database' for me.

For the verification, all I need to have is ApprovalTests.Approvals.Verify().

[UseReporter(typeof(DiffReporter))]
public class ElmahMvcTests
{
 private const string ElmahMvcAppUrl = "http://localhost:49800/elmah";

 [Test]
 public void lock_elmah_mvc_pages()
 {
  // do
  var content = new StringBuilder();            
  var pages = new[] 
      {
       ElmahMvcAppUrl,
       ElmahMvcAppUrl + "/",
       ElmahMvcAppUrl + "/stylesheet",
       ElmahMvcAppUrl + "/rss",
       ElmahMvcAppUrl + "/digestrss",
       ElmahMvcAppUrl + "/detail?id=5dd2a560-c6fd-4847-a6cc-e3e253db5764",
       ElmahMvcAppUrl + "/json?id=5dd2a560-c6fd-4847-a6cc-e3e253db5764",
       ElmahMvcAppUrl + "/xml?id=5dd2a560-c6fd-4847-a6cc-e3e253db5764"
      };

  foreach (var page in pages)
  {
   content.Append(GetContent(page));
  }

  // verify
  ApprovalTests.Approvals.Verify(content.ToString());
 }

The GetContent() is responsible for getting page content. It could be as simple as ApprovalTests.Asp.AspApprovals.GetUrlContents(url), but you might get in the trap, as I did so.

Dealing dynamic data

The trap is called 'Dynamic Data'. Dynamic data is every dynamic part of you output. In my case, the dynamic part was a server time generated by ELMAH and putting into page footer. Of cause, even if I run the test and approve the results, on a next test run I still have red test, since I have differences in a seconds of timestamps in footer. It's annoying, but nothing you can do about it.

My solution was simple. Since I actually don't care about those timestamps at all, I can simple cut it away from output. The rest of the document, including structure and content would remain the same, so testing quality will not be lower.

So, the GetContent() method will look as follows,

private string GetContent(string url)
{
 return RemoveFooter(ApprovalTests.Asp.AspApprovals.GetUrlContents(url));
}

private string RemoveFooter(string content)
{
 var pattern = "<p id=\"Footer\">(.*)</p>";
 return new Regex(pattern).Replace(content, string.Empty);
}

Approving the results

After I had stable test output, I safely approved that test. Approving in terms of ApprovalTest framework, is simple copy of Accepted file into Approved file.

Now the system got into 'Locked' state and I'm safe to do the changes. This is something as Llewellyn mentioned 100% test coverage with one test. Indeed, having only one test and spent 10 minutes to create it I covered huge piece of functionality.

Keep that safe

After I applied all my changes, I re-run approval test to see how it works. I was happy to see, that I'm still generating the same output as it was before. It means, the system still functions as it's expected. All routes works, generated content does not have differences inside. Cool!

As I said earlier, you don't need to keep the test for all time. In my case, as I completed my refactoring and saw that code still works (and of cause, manually tested the application), it's OK just to delete approval test. No longer needed.

Approval.Tests are really shines for a scenarios like that.

Testing

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Cloud Performance Engineering
  • Reliability Is Slowing You Down
  • Building a Real-Time App With Spring Boot, Cassandra, Pulsar, React, and Hilla
  • gRPC on the Client Side

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: