Testando sua view

Ha pouco tempo, resolvendo algumas dividas técnicas de um projeto, me deparei com algumas views que possuíam uma complexidade ciclomática bem elevada.

Olhando com mais atenção, reparei que aqueles “ifs” tinham como finalidade questões simples, como por exemplo, exibir ou não um botão dependendo de um valor que a minha model possuía.

Confesso que fiquei surpreso como, condições simples, podem deixar uma view tão complexa de se entendida depois de algum tempo sem olhar o código.

Para resolver isso,  e de quebra, garantir que essas condições estejam funcionando corretamente, tomei como estrategia criar Alguns HtmlHelpers para separar essas responsabilidades e poder criar testes para os mesmos.

No exemplo abaixo, dependendo do status, disponibilizo link para acesso ao site, ou não.

@model Web.ViewModel.AcessoViewModel
<div class="col-md-12">
    @if (Model != null)
    {
        if (Model.Status == "Disponivel")
        {
            <div class="alert alert-success">
                <a href="http://gustavofontes.net"><i class="glyphicon glyphicon-ok"></i> Acesso Permitido</a></div>
        }
        else if(Model.Status == "Bloqueado")
        {
                <div class="alert alert-danger">
                <span><i class="glyphicon glyphicon-ban-circle"></i> Acesso Negado</span></div>
        }
    }
</div>

Refatorando esse código, criamos um HtmlHelper extension para incapsular a validação:

using System.Web.Mvc;
using Web.ViewModel;

namespace Web.Helpers
{
    public static class DisponibilizarAcesso
    {
        public static MvcHtmlString PermissaoParaAcesso(this HtmlHelper htmlHelper, AcessoViewModel model)
        {

            string html = string.Empty;
            if (model != null)
            {
                if (model.Status == "Disponivel")
                {
                    html = @"
                            <div class='alert alert-success'>
                            <a href='http://gustavofontes.net'><i class='glyphicon glyphicon-ok'></i> Acesso Permitido</a></div>
                           ";
                }
                else if (model.Status == "Bloqueado")
                {
                    html = @"
                             <div class='alert alert-danger'>
                            <span><i class='glyphicon glyphicon-ban-circle'></i> Acesso Negado</span></div>
                            ";
                }

            }
            return MvcHtmlString.Create(html);
        }
    }
}

Para que a view reconheça a extensão que você acabou de criar, no Web.Config que fica dentro da sua pasta Views, adicione o namespace que a mesma pertence:


  <system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Optimization"/>
        <add namespace="System.Web.Routing" />
        <add namespace="Web" />
        <add namespace="Web.Helpers"/>
      </namespaces>
    </pages>
  </system.web.webPages.razor>

No exemplo, a linha 11 foi a linha que eu adicionei. Repare que é o mesmo namespace aonde minha extensão está.

Agora vamos ao teste:

Para testar meu código, eu criei uma nova class library,  via Nuget,  instalei o ASP.NET Mvc e o framework de teste (neste exemplo estou utilizando o NBehave Spec – NUnit).

 

using NBehave.Spec.NUnit;
using NUnit.Framework;
using System.Web.Mvc;
using Web.Helpers;
using Web.ViewModel;
namespace Testandoview.Helpers.Test
{

    public class DadoUmHtmlHelperExtension : SpecBase
    {
        protected string expected;
        protected string actual;
        protected HtmlHelper htmlHelper;
        protected AcessoViewModel viewModel;
        protected override void Establish_context()
        {
            base.Establish_context();
            htmlHelper = new HtmlHelper(new ViewContext(), new ViewPage());
        }
    }

    public class QuandoStatusForDisponivel : DadoUmHtmlHelperExtension
    {


        protected override void Establish_context()
        {
            base.Establish_context();
            viewModel = new AcessoViewModel() { Status = "Disponivel" };
            expected = @"<div class='alert alert-success'>
                            <a href='http://gustavofontes.net'><i class='glyphicon glyphicon-ok'></i> Acesso Permitido</a>
                       </div>";
        }

        protected override void Because_of()
        {
            base.Because_of();

            actual = htmlHelper.PermissaoParaAcesso(viewModel).ToString();

        }
        [Test]
        public void EntaoDisponibilizoLinkDeAcesso()
        {
            actual.ShouldEqual(expected);
        }
    }

    public class QuandoStatusForBloqueado : DadoUmHtmlHelperExtension
    {

        protected override void Establish_context()
        {
            base.Establish_context();
            viewModel = new AcessoViewModel() { Status = "Bloqueado" };
            expected = @"<div class='alert alert-danger'>
                            <span><i class='glyphicon glyphicon-ban-circle'></i> Acesso Negado</span>
                        </div>";
        }

        protected override void Because_of()
        {
            base.Because_of();
            actual = htmlHelper.PermissaoParaAcesso(viewModel).ToString();
        }

        [Test]
        public void EntaoDisponibilizoAvisoDeAcessoNegado()
        {
            actual.ShouldEqual(expected);
        }
    }
}

Pronto! responsabilidade devidamente separada, código fácil de ser entendido e mantido 🙂

O Codigo  de exemplo está no GitHub

Anúncios

2 comentários sobre “Testando sua view

  1. Excelente post, depois de um tempo fazendo esse tipo de if nas views o código vai ficando cada vez mais dificil de ler, utilizando desse tipo de abordagem da para melhorar muito a qualidade do código.

    Curtido por 1 pessoa

    1. Roger, depois que utilizei essa abordagem, posso afirmar que, sem duvidas, facilita muito a leitura e de quebra, com os testes conseguimos ter uma garantia muito boa, mesmo porque, as views não são muito estáveis na nossa aplicação.
      Obrigado pelo feedback 🙂

      Curtir

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s