ASP.NET – Login – Logout – timeout – C#

Publicado: 6 de dezembro de 2014 em C#

Tarefas de gerenciamento de sessão típicas incluem manter o controle de quais aplicativos estão abertos e documentar cada aplicativo que abriu, para que o mesmo estado possa ser restaurado quando o usuário sair e entrar novamente mais tarde. Você também pode utilizar a Session para criar áreas restritas de um website que podem ser acessadas pela sessão de um usuário, você também pode definir um tempo para que esta sessão fique ativa no navegador do usuário autenticado.

Para um site, gerenciamento de sessão pode envolver e exigir que o usuário reinicie sessão se a sessão expirou ou seja, se um certo limite de tempo passou sem a atividade do usuário. A sessão também é usada para armazenar informações no lado do servidor entre solicitações HTTP. Este tipo de conceito básico é o principio do esquema de autenticação utilizado por vários websites, entretanto a partir deste esquema básico pode-se criar métodos mais eficientes para utilizar este conceito.

O uso do ambiente de Sessão do ASP.NET consome recursos do servidor. Atente-se ao utilizar o recurso de tempo de sessão, devemos ser cuidadosos ao definirmos o tempo de duração da sessão inativa, pois quanto maior o tempo, mais irá demorar para o ASP.NET liberar os recursos utilizados.

Session State: http://msdn.microsoft.com/en-us/library/h6bb9cz9(v=vs.85).aspx

Utilizando Sessions – Login, Logout e Timeout

1- Crie uma aplicação do tipo ASP.NET Web Application com o modelo C# Empty e chame seu projeto de DASessionTimeout, crie uma nova pagina WebForm chamada default e uma pagina chamada AreaComunitaria. Copie o código para a pagina e rode o programa.

Você pode tentar chamar a pagina AreaComunitaria sem utilizar o usuário e senha, digitando o nome da pagina na url do navegador e constatará que não pode acessar a pagina devido a inexistência da sessão para seu usuário. Efetue o Login para criar a sessão:

Session - Login

Session – Login

2 – Assim que efetuar o login você será direcionado a área comunitária podendo então acessar a pagina da comunidade, caso clique no link sair, a sessão será invalidada e você será redirecionado para a tela de login:

Session - Área Comunitária

Session – Área Comunitária

3 – Ao incluir as tags de configuração da sessão no arquivo web.config você pode definir o tempo em minutos que deseja que sessão seja valida. Use o código do arquivo xml abaixo para fazer com que a sessão dure 1 minuto, efetue o login, aguarde um minuto e atualize a pagina, com a sessão expirada você será redirecionado novamente para a pagina de login:

Session - Timeout

Session – Timeout

Gerenciamento de Sessão ASP.NET

Este é um modo simples de utilizar uma sessão em ASP.NET e é valido como um exercício, entretanto existem vários outras maneiras mais eficientes de gerenciar ambientes de sessão:

Ambientes de Sessão: http://msdn.microsoft.com/pt-br/library/gg454582.aspx

Exemplo:

Neste exemplo criamos uma pagina de login com a funcionalidade de autenticar em uma pagina somente para membros da comunidade e utilizamos o recurso de timeout da sessão para que ela expire assim que o usuário estiver autenticado por 1 minuto.

Obs: usuário: DevAberto e a senha: 1234

ASP.NET – C#

default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="default.aspx.cs" Inherits="DaSessionTimeout._default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Desenvolvimento Aberto - Login</title>
    <style type="text/css">
        .auto-style1 {
        }
        .auto-style2 {
            width: 103px;
            height: 23px;
        }
        .auto-style3 {
            height: 23px;
        }
        .auto-style4 {
            height: 30px;
        }
    </style>
</head>
<body>
    <h1>Desenvolvimento Aberto</h1>
    <h3>Login:</h3>
    <form id="form1" runat="server">
    <div>

        <table style="width:100%;">
            <tr>
                <td class="auto-style2">
                    <asp:Label ID="Label1" runat="server" Text="Usuário:"></asp:Label>
                </td>
                <td class="auto-style3">
                    <asp:TextBox ID="TextBox1" runat="server"  Width="207px"></asp:TextBox>
                </td>
            </tr>
            <tr>
                <td class="auto-style4">
                    <asp:Label ID="Label2" runat="server" Text="Senha:"></asp:Label>
                </td>
                <td class="auto-style4">
                    <asp:TextBox ID="TextBox2" runat="server" TextMode="Password" Width="207px"></asp:TextBox>
                    <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Entrar" />
                </td>
            </tr>
            <tr>
                <td class="auto-style1" colspan="2">&nbsp;</td>
            </tr>
        </table>

    </div>
    </form>
</body>
</html>

default.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace DaSessionTimeout
{
    public partial class _default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            // Recupera elementos do formulario
            string usuario = Request.Form["TextBox1"];
            string senha   = Request.Form["TextBox2"];

            // Neste exercicio usuario e senhas são fixos
            // Estes dados geralmente estão associados a um banco de dados
            if ( usuario.Equals("DevAberto") && senha.Equals("1234"))
            {
                Session["Usuario"] = usuario;
                Response.Redirect("AreaComunitaria.aspx");
            }
            else
            {
                Response.Redirect("default.aspx");
            }

        }
    }
}

AreaComunitaria.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="AreaComunitaria.aspx.cs" Inherits="DaSessionTimeout.AreaComunitaria" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Desenvolvimento Aberto - ASP.NET - C#</title>
</head>
<body>
    <h1>Desenvolvimento Aberto</h1>
    <h3>Area da Comunidade - C# - ASP.NET</h3>
    <form id="form1" runat="server">
    <div>
       <div>
           <% string usuario = (string)Session["Usuario"];
               Response.Write("Bem Vindo: " + usuario); %>
           <br />
           <asp:LinkButton ID="LinkButton1" runat="server" OnClick="LinkButton1_Click">Sair</asp:LinkButton>
       </div>
    </div>
    </form>
</body>
</html>

AreaComunitaria.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace DaSessionTimeout
{
    public partial class AreaComunitaria : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // Recupera usuario da sessão
            string usuario = (string)Session["Usuario"];

            // Sessão for invalida
            if (usuario == null)
            {
                Response.Redirect("default.aspx");
            }

        }

        protected void LinkButton1_Click(object sender, EventArgs e)
        {
            // Invalida Sessão
            Session.Abandon();
            Response.Redirect("default.aspx");
        }
    }
}

Web.config

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />

  <sessionState timeout="1" />

  </system.web>
</configuration>

ASP.NET – Cookies – C#

Publicado: 5 de dezembro de 2014 em C#

Um cookie é um pequeno pedaço de dados enviado de a partir de um website e armazenado em um arquivo de texto criado no computador do usuário enquanto ele está navegando em um site. Cada vez que o usuário carrega o website, o navegador envia o cookie de volta ao servidor para notificar o site da atividade prévia do usuário. Os cookies foram projetados para serem um mecanismo confiável para sites recordarem informações de estado ou para registrar a atividade de navegação do usuário.

Cookie é um assunto que trouxe e ainda levanta muita controvérsia no universo da computação para web, devido a questões de segurança quanto a manipular informações no computador local, fazem com que todos os tipos de usuários se preocupe com as informações utilizadas em websites principalmente se utilizar computadores que são compartilhados com varias pessoas como em lan houses ou outros.

C# possui a classe HttpCookie que permite que o desenvolvedor manipule cookies em suas aplicações web seguindo as especificações do RFC 2109, está classe representa os valores de um cookie HTTP.

Cookies: https://www.ietf.org/rfc/rfc2109.txt

HttpCookie: System.Web

Utilizando Cookies

1- Crie uma aplicação do tipo ASP.NET Web Application com o modelo C# Empty e chame seu projeto de DACookie, crie uma nova pagina WebForm chamada default. Copie o código para a pagina e rode o programa:

Formulario - Cookie

Formulário – Cookie

2 –  Assim que o botão recebe o evento de clique o método Post cria o cookie no computador local guardando em seu arquivo o nome do usuário, a pagina é recarregada e o cookie é lido automaticamente, toda vez que você tentar recarregar esta página o cookie será lido e o nome guardado automaticamente preenchido:

Cookie

Cookie

Para ver o cookie e no seu navegador (Firefox) abra Opções no menu do Firefox e escolha a aba privacidade:

Firefox - Opções -  Privacidade

Firefox – Opções – Privacidade

4 – Clique no link excluir cookies em particular e digite no campo de busca, localhost. Selecione o cookie pelo seu nome e você pode ver os dados gravados no mesmo. Caso queira testar o exemplo outra vez você pode excluir o cookie e rodar a aplicação novamente:

Firefox - Cookie

Firefox – Cookie

Exemplo:

Neste exemplo criamos uma página que grava e lê um cookie no computador local.

C#

Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="default.aspx.cs" Inherits="DACookies._default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <h1>Desenvolvimento Aberto</h1>
    <h2>Cookies Memoriza Dados</h2>
    <form id="form1" runat="server">
    <div>
    
        <asp:Label ID="Label1" runat="server" Text="Nome: "></asp:Label>
        <asp:TextBox ID="TextBox1" runat="server" Width="292px"></asp:TextBox>
        <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Adicionar" />
    
    </div>
    </form>
</body>
</html>

Default.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace DACookies
{
    public partial class _default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // Recupera Cookie
            HttpCookie cookie = Request.Cookies.Get("DAMeuCookie");

            // Verifica se existe  Cookie 
            if (cookie != null)
            {            
                // Modifica pagina
                Label1.Text = cookie.Value;
                TextBox1.Visible = false;
                Button1.Visible = false;
            }

        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            // Recupera parametro 
            string nome = Request.Form["TextBox1"];
            
            // Cria objeto Cookie
            HttpCookie cookie = new HttpCookie("DAMeuCookie");
            cookie.Value = nome;

            // Adiciona cookie a coleção
            Response.Cookies.Add(cookie);

            // Redireciona pagina
            Response.Redirect("default.aspx");
        }
    }
}

 

SAP – Classes – Objetos e Coleções – Abap

Publicado: 4 de dezembro de 2014 em Abap

Desde que o ABAP Objects foi lançado há vários anos atrás a polemica se instalou na comunidade de desenvolvedores ABAP quanto a utilização do novo paradigma de programação orientado a objeto junto com o antigo paradigma da programação procedural, possibilitando então escrever códigos de múltiplos paradigmas. Varias instruções do antigo paradigma foram marcadas como obsoleta pela SAP que ainda as mantem a nível de compatibilidade com programas mais antigos.

A vinda do novo paradigma causa até hoje enorme e incontáveis batalhas e discussões entre os novos e novos, os novos e velhos e os velhos e velhos desenvolvedores ABAP a fim de chegar a uma argumentação final sobre o assunto que parece não ter solução. Enquanto alguns puristas declaram firmemente que você não pode utilizar instruções do antigo paradigma com instruções orientadas objetos, outros mais liberais não veem nenhum problema nisto já que deste modo a programação se torna muito mais fácil e rápida e ainda contam com o respaldo dos exemplos oficiais disponibilizados pela SAP contidos no NetWeaver que educam os novos desenvolvedores a utilizar os dois paradigmas (transação ABAPDOCU).

Com toda está polemica, é claro que não queremos nos meter no meio deste assunto e nossa opinião não poderia ser mais obvia. Ficar em cima do muro! Pode parecer uma posição meio frouxa, mas garanto que este não é o caso. Se por um lado a programação orientada a objeto é considerada superior a programação procedural, então um código orientado a objeto bem escrito deveria ter uma melhor qualidade, e tem! Mas os exemplos e vários códigos fornecidos, escritos e assinados pela própria SAP misturam os paradigmas, então eu também posso fazer isto, também concordamos!

Já que concordamos com ambas as partes temos que achar o verdadeiro ocasionador de tal desavenças, isto não é tão difícil assim, uma simples busca na documentação oficial e logo encontramos uma da muitas explicações plausíveis para o acontecimento (existem vários pontos que divergem a programação procedural da orientada a objeto e um deles é o próprio Open SQL e os Data Objects, mas isto é assunto para outra ocasião).  Voltando para linha do raciocínio, acontece que a SAP não terminou de implementar o framework de coleções para a linguagem de programação ABAP Objects e indica nos exemplos oficiais um workaround para simular uma LISTA no conceito de programação orientada a objeto, veja no código a implementação do método:  “METHOD WRITE_LIST”.

Isto acontece exatamente no tópico de métodos que são um dos mais importantes elementos que compõem uma classe que obviamente resultará em um objeto. E mais! Também afirma que o exemplo contem instruções obsoletas e não garante a compatibilidade com futuras versões:

“The ABAP statements used for list processing are not yet fully available in ABAP Objects. However, to produce a simple test output, you can use the following statements: WRITE [AT] /<offset>(<length>) <f>
ULINE
SKIP
NEW-LINE

Note: The behavior of formatting and interactive list functions in their current state are not guaranteed. Incompatible changes could occur in a future release.”

Classes: Métodos ABAP

O que é uma lista em programação orientada a objetos?

Em programação orientada a objeto a classe de Lista faz parte do framework de coleções e é equivalente genérico da classe ArrayList . Implementa a interface genérica de listas usando uma matriz cujo tamanho é gerado dinamicamente conforme necessário. Em ABAP podemos dizer que uma lista é semelhante a uma tabela interna que pode conter varias colunas ou linhas, porem é um objeto que pode conter (Container) um objeto criado pelo desenvolvedor e ser manipulado através de outro objeto chamado de iterador.

O ABAP disponibiliza algumas classes para manipular objetos utilizando as coleções porem estas classes ainda não fazem parte de um framework de coleções consistentes como encontramos em outras linguagem com o próprio STL para C++ ou JCF para Java que são as linguagens de programação no qual o ABAP OO foi baseado.

Classes - Manipulando Objetos e Coleções

Classes – Manipulando Objetos e Coleções

Analisando a Classe do Objeto e Utilizando Coleções

Utilizamos um Pattern básico para o objeto criado na classe do código abaixo baseado no que seria comum em qualquer linguagem orientada a objeto como Java e C++.

  1. A classe utiliza encapsulamento privado para os atributos que são os campos primitivos ou não que armazenam valores para o objeto.
  2. Estes campos privados são acessados através dos tradicionais métodos Getter e Setter que são o método Get para ler um atributo do objeto e o método Set para alimentar um atributo do objeto.
  3. Utilizamos um construtor padrão e um construtor Overload para a classe, em ABAP não podemos sobrecarregar os construtores através de métodos e precisamos criar está funcionalidade pela instrução OPTIONAL declarada nos parâmetros das variáveis no escopo do método construtor.
  4. Utilizamos a classe de coleção CL_OBJECT_COLLECTION para criar uma lista para o objeto.
  5. Utilizamos a classe de coleção CL_OBJECT_COLLECTION_ITERATOR  para iterar o objeto de lista.
  6. Para continuar em cima do muro, utilizamos uma instrução FORM-PERFORM para adicionar os objetos na lista e explicamos o motivo nos comentários do código abaixo.

Você ainda pode manipular os objetos da lista, adicionado, removendo, alterando os dados para seu objeto. Mas reiteramos que as coleções ainda não estão totalmente implementadas em ABAP Objetcs o que pode tornar mais difícil este tipo de programação a não ser que você mesmo herde e estenda as classes e implemente seu próprio framework para as coleções.

Mais Questões

Seria o ABAP Objects uma linguagem incompleta? Já que as coleções são de grande importância e essenciais na orientação a objeto uma implementação incompleta justificaria o uso de instruções procedurais para a manipulação de objetos? O Open SQL deixaria o ABAP Objects com um pé no paradigma da programação declarativa já que é utilizado de forma muito similar ao SQL que é uma linguagem declarativa? Manipular dados nos objetos através do Open SQL e Data Objects (Em geral utilizam a instrução DATA) como vemos no exemplo disponibilizado pela SAP no link acima e não através de Patterns de objetos como o DAO (Data Access Objects) para Java entre outros também não quebraria o paradigma da orientação a objeto? Podemos então afirmar que ABAP é uma linguagem exclusivamente de múltiplos paradigmas? Deixaremos que vocês tirem suas próprias conclusões.

DAO Pattern: http://www.oracle.com/technetwork/java/dataaccessobject-138824.html

ABAP: Data Objects

Até o momento não há documentação oficial no site da SAP sobre as classes de coleções.

Object Handling: Manipulando Objetos

Exemplo:

Neste exemplo criamos uma classe que contem alguns recursos básicos da programação orientada a objeto como atributos privados, construtor Overload, métodos Getter e Setter e utilizamos um objeto de lista para armazenar e manipular nosso objeto.

Métodos: Overload

Coleções: Collections Iterator e Collection Map

ABAP

*&---------------------------------------------------------------------*
*& Report  ZABAPOBJETO
*&
*&---------------------------------------------------------------------*
*& Desenvolvimento Aberto
*& Objetos Abap - Manipulando Objetos
*& Classe - Objeto - Lista - Iterador
*&---------------------------------------------------------------------*

REPORT  ZABAPOBJETO.

* Cria classe Participante
class ZPARTICIPANTE definition.

  public section.

* Declara construtor com efeito Overload
    methods CONSTRUCTOR IMPORTING
               pid    TYPE i      OPTIONAL
               pnome  TYPE string OPTIONAL
               pidade TYPE i      OPTIONAL.

* Declara métodos Getter e Setter

    methods SETID importing  !PID type i .
    methods GETID returning value(RESULTADO) type i .
    methods SETNOME importing  !PNOME type STRING .
    methods GETNOME returning value(RESULTADO) type STRING .
    methods SETIDADE importing !PIDADE type I .
    methods GETIDADE returning value(RESULTADO) type I .

* Declara atributos privados
  private section.

    data ID    type i.
    data NOME  type STRING .
    data IDADE type I .

ENDCLASS.

* Implementação da classe
CLASS ZPARTICIPANTE IMPLEMENTATION.

*  Construtor

  METHOD CONSTRUCTOR.
    me->ID = PID.
    me->NOME = PNOME.
    me->IDADE = PIDADE.
  ENDMETHOD.

*  Metodos Getter e Setter

  METHOD GETIDADE.
    RESULTADO = me->IDADE.
  ENDMETHOD.

  METHOD GETNOME.
    RESULTADO = me->NOME.
  ENDMETHOD.

  METHOD GETID.
    RESULTADO = me->ID.
  ENDMETHOD.

  METHOD SETIDADE.
    me->IDADE = PIDADE.
  ENDMETHOD.

  METHOD SETNOME.
    me->NOME = PNOME.
  ENDMETHOD.

  METHOD SETID.
    me->ID = PID.
  ENDMETHOD.

ENDCLASS.

* testa programa
START-OF-SELECTION.

* Testa Classe
  DATA: p1    TYPE REF TO ZPARTICIPANTE,
        p2    TYPE REF TO ZPARTICIPANTE,
        id    TYPE i,
        nome  TYPE String,
        idade TYPE i.

* Istancia Objeto usando Construtor Overload
  CREATE OBJECT P1
    EXPORTING
      PID    = 1
      PNOME  = 'José Pereira'
      PIDADE = 35.

* Métodos Getter
  id    = p1->GETID( ).
  nome  = P1->GETNOME( ).
  idade = P1->GETIDADE( ).

* Imprime valores P1
  WRITE: / 'Valor do Objeto P1: ', id, nome, idade.

*Instancia Objeto padrão

  CREATE OBJECT P2.
* Métodos Setter
  p2->SETID( 2 ).
  p2->SETNOME( 'Joao da Silva' ).
  p2->SETIDADE( 20 ).

* Métodos Getter
  id    = p2->GETID( ).
  nome  = P2->GETNOME( ).
  idade = P2->GETIDADE( ).

* Imprime valores P2
  WRITE: / 'Valor do Objeto P2: ', id, nome, idade.

SKIP 2.
WRITE : / 'Objetos da lista:'.
SKIP 1.

* ***********************************************
* ************* Manipulando Objetos *************
* ***********************************************
*
*
* Define Lista para iterar objetos
* Listas e iteradores fazem parte do framework de coleções
* São o meio padrão para manipular objetos
* No entanto em ABAP Objects as coleções não
* foram totalmente implementadas.

* Declara instancia da classe para a lista
  DATA ITEM TYPE REF TO ZPARTICIPANTE.

* Declara objeto de lista e iterador
  DATA LISTA TYPE REF TO CL_OBJECT_COLLECTION.
  DATA ITERADOR TYPE REF TO CL_OBJECT_COLLECTION_ITERATOR.

* Cria lista
  CREATE OBJECT LISTA.

* Adiciona Objeto a lista
  PERFORM ADD USING 3 'Mario Alvim' 27.
  PERFORM ADD USING 4 'Fernando Moraes' 45.
  PERFORM ADD USING 5 'Eduardo gonçalves' 38.

* Atribui objeto ao Iterador
  ITERADOR = LISTA->GET_ITERATOR( ).

* Usa iterator como um cursor de banco de dados
  WHILE ITERADOR->HAS_NEXT( ) IS NOT INITIAL.

    " Verifica objetos da lista
    ITEM ?= ITERADOR->GET_NEXT( ).

    " Alimenta objeto
    id = ITEM->GETID( ).
    nome = ITEM->GETNOME( ).
    idade = ITEM->GETIDADE( ).

    " Imprime dados do objeto
    WRITE : / id, nome, idade.

  ENDWHILE.

* Cria uma polemica instrução FORM-PERFORM
* Seria possivel criar uma classe com um método estatico
* para executar a mesma função desta sub-rotina
* mas encapsular os objetos criados daria muito mais trabalho
* do que mesclar Objetos e uma instrução procedural.
*
* Desde que as Coleções não estão totalmente implementadas em ABAP OO
* Exemplos utilizando o FORM-PERFORM para criar objetos
* são muito comuns mesmo nos exemplos disponibilizados pela SAP
* você pode conferir nos exemplos do NETWEAVER basta procurar na transação
* ABAPDOCU e vai encontrar varios exemplos utilizando objetos inicializados com FORM-PERFORM
* Este processo seria equivalente a uma VOID em C++ ou Def em Python ou Ruby que pode estar
* tanto dentro de uma classe como um método ou fora de uma classe como um procedimento.

FORM ADD USING VALUE(pid)  TYPE i
               VALUE(pnome) TYPE string
               VALUE(pidade) TYPE i.

* Cria objeto da classe como item
  CREATE OBJECT ITEM
    EXPORTING
      PID    = pid
      PNOME  = pnome
      PIDADE = pidade.

* Adiciona a lista
  LISTA->ADD( ITEM ).

ENDFORM.

ASP.NET – Responses – Status Code – C#

Publicado: 3 de dezembro de 2014 em C#

A cada solicitação do protocolo HTTP o servidor indica uma resposta provisória, consistindo somente da linha de status e cabeçalhos opcionaisencerrado por uma linha vazia. As respostas podem conter por exemplo erros de HTTP que são enviados para o navegador da Web pelo servidor se um problema for encontrado durante a tentativa de exibir uma página da Web. Se a página da Web não for exibida, o servidor exibirá a página de erro real enviada pelo site ou uma mensagem de erro amigável.

As vezes é útil criar uma pagina customizada para as paginas geradas automaticamente pelo servidor pois o mesmo pode mostrar nestas paginas informações que não queremos que o usuário remoto tenha conhecimento, além das boas praticas e uma mensagem esteticamente amigável, ainda temos entre os motivos, a segurança.

Para uma lista completa de todos os códigos de resposta enviados pelo servidor utilize o link abaixo:

Response Status Code: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

Customizando uma Página de Erro

11- Crie uma aplicação do tipo ASP.NET Web Application com o modelo C# Empty e chame seu projeto de DAWebStatusCode, crie uma nova pagina html chamada default. Copie o código para a pagina e rode o programa:

Default.html

Default.html

2 – Clique no link “ASP.NET” para que você obtenha a pagina de erro com a resposta gerada pelo servidor:

ASP.NET - Erro

ASP.NET – Erro

3 – Para substituir a pagina automática por uma pagina mais amigável precisamos capturar a resposta do servidor e exibir uma pagina com informações customizadas, entretanto não queremos que o usuário tenha acesso a esta pagina via o navegador, então precisamos criar uma pagina chamada de 404.html e alterar o web.config, redirecionando a resposta 404 para a pagina 404.html. Crie a pagina 404.html e altere o arquivo web.config utilizando os respectivos códigos abaixo, em seguida rode a aplicação:

Default.html

Default.html

4 – Clique novamente na opção “ASP.NET” e sua pagina customizada será exibida sem que nenhuma informação do servidor e de sua aplicação seja apresentada para o usuário remoto:

Erro - Customizado

Erro – Customizado

Entretanto ASP.NET possui algumas configurações diferenciadas, por exemplo no arquivo Web.Config, toda a configuração para paginas de erro customizadas em ASP.NET necessitam estar dentro da tag <system.web> na tag  <customErrors> enquanto as configurações para erros HTTP necessitam estar na tag <configuration> na tag <system.webserver>.

ASP.NET Custom Error: http://msdn.microsoft.com/pt-br/library/h0hfz6fc(v=vs.85).aspx

System.webServer: http://msdn.microsoft.com/pt-br/library/bb763179(v=vs.100).aspx

Exemplo:

Neste exemplo utilizamos a resposta do servidor para substituir a mensagem de erro 404 por uma mensagem exibida em uma pagina customizada. Como estamos utilizando uma aplicação que utiliza paginas html em um modelo vazio, a configuração de erro que possui efeito é a contida nos elementos system.webServer.

HTML

default.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Desenvolvimento Aberto - HTTP Respostas</title>
    <style>
        #header {
            background-color: Black;
            color: white;
            text-align: center;
            padding: 5px;
        }

        #nav {
            line-height: 30px;
            background-color: #eeeeee;
            height: 400px;
            width: 100px;
            float: left;
            padding: 5px;
        }

        #section {
            width: 450px;
            float: left;
            padding: 10px;
        }

        #footer {
            background-color: Black;
            color: white;
            clear: both;
            text-align: center;
            padding: 5px;
        }
    </style>

</head>
<body>
    <div id="header">
        <h1>Desenvolvimento Aberto</h1>
    </div>

    <div id="nav">

        <!-- HTTP Response:

         Este link referencia uma página que não existe,
         deste modo o servidor nos enviará um erro 404  -->
        <p>
            <a href='nao-existe.html'>ASP.NET</a>
        </p>
        <p>Web Forms</p>
        <p>MVC</p>
        <p>C#</p>

    </div>

    <div id="section">
        <h2>Desenvolvimento Aberto</h2>
        <p>
            Desenvolvimento Aberto é uma organização voltada para o
            aprendizado e discussão de técnicas de desenvolvimento focado em
            algumas linguagens de programação sendo parcialmente/totalmente
            abertas ou com licenças gratuitas para desenvolvedores de cada uma de
            suas respectivas marcas registradas.
        </p>
        <p>
            Desenvolvimento Aberto foi escrito e desenvolve utilizando
            ferramentas gratuitas disponibilizadas pelas melhores empresas de
            software da atualidade, incluindo a própria hospedagem e design deste
            site, sendo assim, também proporciona conteúdo gratuito, isso quer
            dizer que você não paga nada para aprender e utilizar as tecnologias
            de ponta que podem ser manuseadas através das linguagens de
            programação mais requisitadas pelas empresas no mercado atual.
        </p>
    </div>

    <div id="footer">
        Desenvolvimento Aberto ©
        desevolvimento.aberto@live.com
    </div>

</body>
</html>

404.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body>
    <h1>Desenvolvimento Aberto</h1>
    <h3>Desculpe! Não encontramos a página solicitada no servidor</h3>
    <p>Erro: HTTP 404. </p>
</body>
</html>

web.config

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />

    <customErrors defaultRedirect="GenericError.htm"
                 mode="On">
      <error statusCode="404"
             redirect="404.html"/>
    </customErrors>
  </system.web>

  <system.webServer>
    <httpErrors errorMode="Custom">
      <remove statusCode="404"/>
      <error statusCode="404" path="404.html" responseMode="ExecuteURL"/>
    </httpErrors>
  </system.webServer>
  
</configuration>

Sabendo que a tecnologia Active Server Pages proporcionada pelo servidor de aplicação nos possibilita criar aplicações web dinâmicas utilizando .NET, vamos então criar um motor básico que utiliza o principio usado por quase todas as aplicações web para o mundo corporativo, ou seja manipulação de dados.

Em aplicações Enterprise os dados na grande maioria das vezes é manipulado através de um servidor de banco de dados relacional, entretanto neste primeiro exemplo vamos utilizar um objeto C# que possibilita a criação de listas para manipular os dados, ressaltando o que realmente nos interessa neste momento é apenas o esqueleto de uma simples aplicação que mostra, adiciona, edita e deleta dados através de uma interface com o usuário.

Criando uma Aplicação Web C#

1- Crie uma aplicação do tipo ASP.NET Web Application com o modelo C# Empty e chame seu projeto de DAWebApp, crie uma nova pagina WebForms chamada default. Crie também uma classe chamada Menssagem. Utilize o código abaixo para cada respectivo arquivo e compile a aplicação:

Default - Mostra grade de dados

Default – Mostra grade de dados

2 – Para adicionar dados utilizamos a pagina adados.aspx (add),  que contem os componentes de acordo com os arquivos abaixo:

adados.aspx - adiciona dados

adados.aspx – adiciona dados

3 – Para editar os dados utilizamos a pagina udados.aspx (update) que contem os componentes de acordo com os arquivos abaixo:

udados.aspx - editar dados

udados.aspx – editar dados

4 – Para remover os dados utilizamos a pagina ddados.aspx (delete) cujo código esta disponível também logo abaixo:

ddados - deleta dados

ddados – deleta dados

Exemplo:

Neste exemplo utilizamos o conceito básico de manipulação de objetos utilizando objetos de lista, que fazem parte do framework de coleções do C#.

Este modelo de aplicação utilizando lista armazena o objeto em uma sessão do servidor de aplicação, tente abrir um outro navegador como o Firefox por exemplo, enquanto roda sua aplicação no Internet Explorer, alimente dados na lista e você irá constatar que devido o uso da sessão cada navegador possui uma lista com dados distintos, já que cada um utiliza uma sessão diferente.

C#

Objeto – Menssagem.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace DaWebApp
{
    public class Menssagem
    {
        // Declara atributos
        private int id;
        private string nome;
        private string menssagem;

        // Construtor padrão
        public Menssagem() { }

        // Construtor Overload
        public Menssagem(int id, string nome, string menssagem)
        {
            // Inicializa valores;
            this.id = id;
            this.nome = nome;
            this.menssagem = menssagem;
        }

        // Propriedades
        public int Id
        {
            get
            {
                return id;
            }
            set
            {
                id = value;
            }
        }

        public string Nome
        {
            get
            {
                return nome;
            }

            set
            {
                nome = value;
            }
        }

        public string Msg
        {
            get
            {
                return menssagem;
            }
            set
            {
                menssagem = value;
            }
        }
    }
}

default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="default.aspx.cs" Inherits="DaWebApp._default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

    </div>
    </form>
</body>
</html>

default.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace DaWebApp
{
    public partial class _default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (Session["registros"] == null)
            {
                // Cria lista para o objeto
                List<Menssagem> msg = new List<Menssagem>();

                // Adiciona dados ao objeto
                msg.Add(new Menssagem(1, "Ricardo", "Olá Pessoal"));
                msg.Add(new Menssagem(2, "Mantovani", "Bem-vindos ao Desenvolvimento Aberto," +
                                      " adicione, altere e exclua dados desta tabela"));

                // Adiciona objeto a sessão
                Session["registros"] = msg;
            }

            // Cria pagina no método HTTP GET
            if (Request.HttpMethod.Equals("GET"))
            {
                doGet();
            }
        }

        private void doGet()
        {
            // Cria estilo CSS
            Response.Write("<head>");
            Response.Write("<style>");
            Response.Write("td, th {");
            Response.Write("border: none;");
            Response.Write("background-color: #dddddd;");
            Response.Write("padding: 5px;");
            Response.Write("width: 200px; }");
            Response.Write("</style>");
            Response.Write("</head>");

            // Titulo da pagina
            Response.Write("<h1>Desenvolvimento Aberto - Listas </h1>");

            // Cria tabela
            Response.Write("<table>");
            Response.Write("<tr>");
            Response.Write("<th>ID:</th>");
            Response.Write("<th>Nome:</th>");
            Response.Write("<th>Comentário:</th>");
            Response.Write("<th>Ação:</th>");
            Response.Write("</tr>");

            // Recupera objeto da sessão
            List<Menssagem> registros = (List<Menssagem>)Session["registros"];

            // Itera objeto
            foreach (Menssagem reg in registros)
            {
                Response.Write("<tr>");
                Response.Write("<td>" + reg.Id + "</td>");
                Response.Write("<td>" + reg.Nome + "</td>");
                Response.Write("<td>" + reg.Msg + "</td>");

                // Link de edição
                Response.Write("<td><center>");
                Response.Write("<a href='udados.aspx?identificador=" + reg.Id + "'>Editar</a> | ");
                Response.Write("<a href='ddados.aspx?identificador=" + reg.Id + "'>Apagar</a>");
                Response.Write("</center></td>");
                Response.Write("</tr>");
            }

            Response.Write("</table>");

            // Define link para formulario de adicionar dados
            Response.Write("<P> <a href='adados.aspx'>Adicione um comentário</a> </p>");
        }
    }
}

adados.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="adados.aspx.cs" Inherits="DaWebApp.adados" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <h1>Desenvolvimento Aberto - Adiciona Menssagem</h1>
    <form id="form1" runat="server">
    <div>

        <asp:Label ID="Label2" runat="server" Text="Id:entificador  "></asp:Label>
        <br />
        <asp:TextBox ID="TextBox1" runat="server" Width="135px"></asp:TextBox>
        <br />

        <asp:Label ID="Label1" runat="server" Text="Nome:"></asp:Label>
        <br />
        <asp:TextBox ID="TextBox2" runat="server" Width="229px"></asp:TextBox>
        <br />
        <br />
        <asp:TextBox ID="TextBox3" runat="server" Height="118px" TextMode="MultiLine" Width="269px"></asp:TextBox>

        <br />
        <br />
        <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Adicionar" Width="274px" />

    </div>
    </form>
</body>
</html>

adados.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace DaWebApp
{
    public partial class adados : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            // recupera parametro
            string parametro = Request.QueryString["identificador"];

            // Recupera objeto da sessão
            List<Menssagem> registros = (List<Menssagem>)Session["registros"];

            // Adiciona registros
            registros.Add(new Menssagem(Convert.ToInt32(TextBox1.Text), TextBox2.Text, TextBox3.Text));
            Response.Redirect("default.aspx");
        }
    }
}

udados.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="udados.aspx.cs" Inherits="DaWebApp.udados" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <h1>Desenvolvimento Aberto - Altera Dados</h1>
    <form id="form1" runat="server">
    <div>
        <asp:Label ID="Label1" runat="server" Text="Identificador:"></asp:Label>
        <br />
        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
        <br />
        Nome:<br />
        <asp:TextBox ID="TextBox2" runat="server" Width="194px"></asp:TextBox>
        <br />
        <br />
        <asp:Label ID="Label2" runat="server" Text="Menssagem:"></asp:Label>
        <br />
        <asp:TextBox ID="TextBox3" runat="server" Height="122px" TextMode="MultiLine" Width="209px"></asp:TextBox>

        <br />
        <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Alterar" Width="112px" />

    </div>
    </form>
</body>
</html>

udados.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace DaWebApp
{
    public partial class udados : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // Verifica se a resposta não é um postback
            if (!IsPostBack)
            {
                // Recupera parametro
                string parametro = Request.QueryString["identificador"];

                // Alinha ID com indice da lista
                int id = Convert.ToInt32(parametro);
                id -= 1;

                // Recupera objeto da sessão
                List<Menssagem> registros = (List<Menssagem>)Session["registros"];

                // Exibe objeto
                if (Session["registros"] != null)
                {
                    TextBox1.Text = Convert.ToString(registros[id].Id);
                    TextBox2.Text = registros[id].Nome;
                    TextBox3.Text = registros[id].Msg;
                }
            }
        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            // Recupera parametro
            string parametro = Request.QueryString["identificador"];

            // Alinha ID com o indice
            int id = Convert.ToInt32(parametro);
            id -= 1;

            // Recupera obeto da sessão
            List<Menssagem> registros = (List<Menssagem>)Session["registros"];

            // Altera propriedades da  lista
            registros[id].Id = Convert.ToInt32(TextBox1.Text);
            registros[id].Nome = TextBox2.Text;
            registros[id].Msg = TextBox3.Text;

            // Redireciona pagina
            Response.Redirect("default.aspx");

        }
    }
}

ddados.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ddados.aspx.cs" Inherits="DaWebApp.ddados" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

    </div>
    </form>
</body>
</html>

ddados.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace DaWebApp
{
    public partial class ddados : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // Recupera parametro
            string parametro = Request.QueryString["identificador"];

            // Alinha ID com indice da lista
            int id = Convert.ToInt32(parametro);
            id -= 1;

            // Recupera objeto da sessão
            List<Menssagem> registros = (List<Menssagem>)Session["registros"];

            // Remove registro da lista
            registros.RemoveAt(id);

            // Alinha indice com ID
            id += 1;

            // Define Menssagem ao usuario
            Response.Write("<h1>Desenvolvimento Aberto</h1>");
            Response.Write("Registro: ID:" + id + " removido com sucesso <br>");
            Response.Write("<a href='default.aspx'>Voltar</a>");

        }
    }
}

ASP.NET – Session Scope – C#

Publicado: 1 de dezembro de 2014 em C#

O escopo de um objeto descreve a disponibilidade de sua abrangência e quem tem acesso a ele. Por exemplo, se um objeto é definido para ter alcance a uma pagina página, então ele está disponível apenas durante a duração da solicitação atual nessa página antes de ser destruído. Neste caso, somente a página atual tem acesso a esses dados, e ninguém mais pode lê-lo. No outro extremo da escala, se um objeto tem espaço de aplicação, em seguida, qualquer página pode utilizar os dados porque ele estará disponível durante toda a aplicação.

Um objeto da sessão é mantido para cada usuário que solicita uma página ou documento de um aplicativo ASP.NET. Variáveis armazenadas no objeto Session não são descartadas quando o usuário move a partir de uma página para outra no pedido; em vez disso, essas variáveis persistem enquanto o usuário está acessando páginas em seu aplicativo.

Page Class

Representa um arquivo .aspx, também conhecida como uma página Web Forms, solicitada a partir de um servidor que hospeda um aplicativo Web ASP.NET.

Page.Session Property

Obtém o objeto Session atual fornecido pelo ASP.NET.

Utilizando Variáveis de Sessão

1- Crie uma aplicação do tipo ASP.NET Web Application com o modelo C# Empty e chame seu projeto de AspNetSessionScope, crie uma nova pagina WebForms chamada default. Crie também uma classe chamada Cor. Utilize o código abaixo para cada respectivo arquivo e compile a aplicação:

Página Inicial

Página Inicial

2 – O evento Page_Load cria uma instancia do objeto da classe Cor e modifica o valor da cor do elemento DIV da pagina aspx de acordo com o valor inicializado pelo construtor do objeto Cor.

  • Abra uma nova aba do navegador e copie e cole a url da pagina, você deve obter duas paginas com o texto vermelho.
  • Volte na primeira aba e inclua o parâmetro cor no final da url e pressione enter: ?Cor=blue
Alimenta Paramêtro

Alimenta Parâmetro

3 – A cor foi modificada e o valor do parâmetro foi armazenado em uma variável de sessão que responsável por alterar a cor do elemento DIV nas seguintes condições:

  • Se existir um parâmetro ou se houver uma variável de cor atrelada a sessão.
  • Selecione a outra aba e a cor do elemento DIV ainda permanece vermelha, atualize a pagina e pronto a pagina mudará a cor do elemento DIV de acordo com a cor armazenada na sessão.
  • Você pode mudar a cor do parâmetro na primeira aba e atualizar a pagina na segunda aba quantas vezes quiser, pode ainda abrir outras abas e a cor do elemento DIV sempre utilizara a cor armazenada na sessão da aplicação.
  • Abra outro navegador, cole a url da segunda aba sem o parâmetro e poderá ver que ele inicializou a cor do objeto Cor (vermelho) porque possui sua própria sessão.
Aba 2 - Sessão

Aba 2 – Sessão

Exemplo:

Neste exemplo criamos uma pagina que lê a cor de um objeto e armazena em uma sessão, você pode modificar a cor através de um parâmetro, abrir novas abas no mesmo navegador e verificar como funciona uma variável de sessão. Você também pode abrir outro navegador e verificar que a variável é inicializada novamente por se tratar de uma nova sessão.

C#

Cor.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace AspNetSessionScope
{
    public class Cor
    {
        // Declara atributo
        private string cor;

        public Cor()
        {
            // Inicializa cor no construtor
            cor = "red";
        }

        // Propriedades
        public string MinhaCor
        {
            get
            {
                return cor;
            }

        }
    }
}

default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="default.aspx.cs" Inherits="AspNetSessionScope._default" %>
<%@ Import Namespace="AspNetSessionScope" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Desenvolvimento Aberto</title>
    <style type="text/css">

#MeuDiv {
    background-color: lightgrey;
    width: 300px;
    padding: 25px;
    border: 20px solid black;
    margin: 25px;
}

</style>
</head>
<body>
    <form id="form1" runat="server">
    <div id="MeuDiv" runat="server">
    <h1>ASP.NET - Desenvolvimento Aberto</h1>

    <h2>Escopo da Sessão - Cor</h2>

    <h3>Este é o valor da cor:</h3>
        <%
            // Se existir sessão utiliza cor
            // se não existir utiliza instancia do objeto
            string sessionCor = (string)Session["scor"];

            if (sessionCor == null)
            {
                Cor cor = new Cor();
                Response.Write(cor.MinhaCor);
            }
            else
            {
                Response.Write(sessionCor);
            }
        %>
    </div>
    </form>
</body>
</html>

default.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace AspNetSessionScope
{
    public partial class _default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // Define cor inical
            Cor cor = new Cor();
            MeuDiv.Style["color"] = cor.MinhaCor;

            // Recupera parmetro
            string parametro = Request.QueryString["Cor"];

            if (parametro != null)
            {
                // Modifica DIV e guarda cor na sessão
                MeuDiv.Style["color"] = parametro;
                Session["scor"] = parametro;
            }
            else
            {
                // Se existir sessão modifica DIV
                if (Session["scor"] != null)
                {
                    string sessionCor = (string)Session["scor"];
                    MeuDiv.Style["color"] = sessionCor;
                }
            }
        }
    }
}

SAP – ABAP Unit – Testes Unitários – Abap

Publicado: 30 de novembro de 2014 em Abap

A maioria das metodologias disponíveis para o desenvolvimento de software e gerenciamento de projetos incluem como pratica básica essencial o desenvolvimento e execução de testes unitários para que um projeto de desenvolvimento possa passar para próxima fase.

Uma boa execução de um projeto bem elaborado em diversas metodologias utilizam ambientes e exigem que os testes unitários sejam executados no ambiente de desenvolvimento (DEV) utilizando uma ferramenta para este proposito e reexecutados por consultores  funcionais/testadores, na fase de testes unitários no ambiente real de qualidade (QAS) para que só então possam executar a fase de testes integrados antes de aprovarem e homologarem o software para utilização em um ambiente produtivo (PRD).

O teste unitário executado do ponto de vista do setor de qualidade (QAS) é feito validando todas as partes dos software, incluindo, design intuitivo, usabilidade, teclas de atalho, layouts, grafia, links e etc. É claro que existem algumas diferenças sutis entre metodologias, como um ou outro procedimento ou diferentes nomenclaturas mas no final todas possuem o mesmo proposito, um software de qualidade, livre de erros e dentro do orçamento inicial do projeto. Bem! No mundo real, não importa qual a metodologia escolhida, isto nem sempre é possível.

Contudo a SAP possui sua própria metodologia desenvolvida ao longo de 40 anos de experiência no mercado para software corporativo, e muitos destes anos como líder mundial em software empresarial, podemos afirmar que sua metodologia é comprovadamente eficiente e durante a evolução de seu desenvolvimento influenciou muitas outras metodologias de software existentes e vice versa, a nova versão da metodologia SAP também incorporou o DNA dos polêmicos métodos de desenvolvimento ágil e assim o ASAP 8 conta com duas aproximações da metodologia, o  Standard ASAP e Agile ASAP.

ASAP: http://scn.sap.com/community/asap-methodology

ABAP Unit

ABAP Unit é parte do ambiente de teste para programas ABAP. Unidade ABAP permite a implementação de testes de unidade e  execução manual e automática. Testes de unidade ABAP são métodos de classes ABAP especialmente designados. Os métodos de ensaio funcionam como scripts, com o qual o código a ser testado pode ser executado, e com a qual o resultado como em um ensaio pode ser avaliado. ABAP OO é conceitualmente parecido com Java e C++, deste modo os teste unitários ABAP são similares ao JUnit do Java. O ABAP Unit é adequado para desenvolvimento orientado a testes (TDD).

ABAP Unit: Abap Unit Overview

Executando Testes Unitários com  ABAP Unit

Os testes unitários ABAP podem ser escritos para classes ou para funções. Existe dois principais métodos de criar um teste unitário, eles são Global ou Local.

Global :

1 – Abra o Class Builder e crie uma classe chamada ZParticipante, com os seguintes atributos (você pode utilizar o código abaixo para se basear na criação da classe):

Classe - Atributos

Classe – Atributos

2 – Crie os seguintes métodos para a classe:

Classe - Métodos

Classe – Métodos

3 – Na barra de ferramentas clique em Source-Code Based e preencha os métodos para a classe ZParticipante de acordo com  a classe do código abaixo:

Classe - Implementação

Classe – Implementação

4 – Para criar uma classe de testes clique no menu Utilities->Test Class Generation e você será guiado pelo Wizard sobre como criar a classe de teste (Utilize a classe de teste encontrada abaixo para preencher o Wizard e implementar os métodos gerados).

  • Para acessar a classe de testes, no menu GO TO->Local Definitions/Implementation-> Local Test Classes.
  • Para testar os métodos clique no menu Class Source->Unit Test
Classe Teste - Wizard

Classe Teste – Wizard

Teste Unitário – ABAP Unit – Métodos

Um modo de testar um objeto é testando seus métodos Setters e retornando os métodos Getters como comparação, evitando assim erros de logica no objeto, além destes métodos você pode testar outros métodos do objeto como achar melhor:

1 – Caso não queira utilizar o método Global você pode testar classes locais diretamente de um programa ABAP, entre na transação SE38 e crie um programa chamado ZDAUNITESTE e utilize o código abaixo, compile e teste.

  • Para executar o teste unitário na classe, o procedimento é o mesmo do procedimento global, no menu Program->Test->Unit Test.
  • Para obter um erro no método substitua o valor de comparação no método ASSERT por um valor diferente do código abaixo:
Teste Unitário - Erros

Teste Unitário – Erros

2 – Corrija o código da classe de teste de acordo com o código abaixo e rode o teste novamente:

Teste Unitário - OK

Teste Unitário – OK

Exemplo:

Neste exemplo criamos uma simples classe com métodos Getter e Setter e uma classe de caso de teste para efetuar um teste unitário nos métodos criados.

Obs: O método utilizado para o testar o código abaixo é executado em um programa local, de modo local, caso queira testar classes globais com a classe de teste atrelada a classe testada, utilize os trechos das classes abaixo para criar as classes pelos Wizards do Class Builder como mostra as figuras acima.

ABAP

Classe – Participante

*&---------------------------------------------------------------------*
*& Report  ZDAUNITESTE
*&
*&---------------------------------------------------------------------*
*& Desenvolvimento Aberto
*& Testes unitários - ABAP
*&---------------------------------------------------------------------*

REPORT  ZDAUNITESTE.

* Cria classe Participante
class ZPARTICIPANTE definition.

  public section.

* Declara métodos Getter e Setter

    methods SETNOME importing  !PNOME type STRING .
    methods GETNOME returning value(RESULTADO) type STRING .
    methods SETIDADE importing !PIDADE type I .
    methods GETIDADE returning value(RESULTADO) type I .

  protected section.

* Declara atributos privados
  private section.

    data NOME type STRING .
    data IDADE type I .

ENDCLASS.

* Implementação da classe
CLASS ZPARTICIPANTE IMPLEMENTATION.

*  Metodos Getter e Setter

  METHOD GETIDADE.
    RESULTADO = me->IDADE.
    "Inverta o código acima: me->IDADE = RESULTADO
    "Você vai obter um erro de lógica
    "Passara pelo compilador ABAP
    "Mas não passara pelo teste Unitário
    "Deste modo você previne erros escritos
    "por desatenção ou desenvolvimento emergências
    "como nos Sprints em algumas metodologias

  ENDMETHOD.

  METHOD GETNOME.
    RESULTADO = me->NOME.
  ENDMETHOD.

  METHOD SETIDADE.
    me->IDADE = PIDADE.
  ENDMETHOD.

  METHOD SETNOME.
    me->NOME = PNOME.
  ENDMETHOD.
ENDCLASS.

* testa programa
START-OF-SELECTION.

* Testa Classe
  DATA: p1    TYPE REF TO ZPARTICIPANTE,
        nome  TYPE String,
        idade TYPE i.

* Istancia Objeto
  CREATE OBJECT P1.

* Métodos Setter
  p1->SETNOME( 'Joao da Silva' ).
  p1->SETIDADE( 20 ).

* Métodos Getter
  nome =  P1->GETNOME( ).
  idade = P1->GETIDADE( ).

* Imprime valores
  WRITE: / nome, idade.

* Classe de Teste Unitário.
* Na definição da classe de teste abaixo:
* "#AU Risk_Level Harmless não é um comentário
* e sim um decorador indicando o nível risco do teste
* sem este decorador a classe não testará os métodos.

CLASS ZPARTICIPANTE_TEST DEFINITION FOR TESTING."#AU Risk_Level Harmless

  PUBLIC SECTION.

    METHODS:
      SETNOME FOR TESTING,
      SETIDADE FOR TESTING.

ENDCLASS.

CLASS ZPARTICIPANTE_TEST IMPLEMENTATION.

* Teste unitario para metodos Getter e Setter
  METHOD SETNOME.

    DATA p1 TYPE REF TO ZPARTICIPANTE.
    CREATE OBJECT p1.

    p1->SETNOME('Nome').
    cl_aunit_assert=>ASSERT_EQUALS(
      exporting
        EXP                  =     'Nome'          " Data Object with Expected Type
        ACT                  =     p1->GETNOME( )  " Data Object with Current Value

    ).
  ENDMETHOD.

  METHOD SETIDADE.
    DATA p2 TYPE REF TO ZPARTICIPANTE.
    CREATE OBJECT p2.

    p2->SETIDADE( 20 ).
    cl_aunit_assert=>ASSERT_EQUALS(
      exporting
        EXP                  =     20          " Data Object with Expected Type
        ACT                  =     p2->GETIDADE( )  " Data Object with Current Value

    ).
  ENDMETHOD.

ENDCLASS.

PyCharm – Testes Unitários – Python

Publicado: 28 de novembro de 2014 em Python

A maioria das metodologias disponíveis para o desenvolvimento de software e gerenciamento de projetos incluem como pratica básica essencial o desenvolvimento e execução de testes unitários para que um projeto de desenvolvimento possa passar para próxima fase.

Uma boa execução de um projeto bem elaborado em diversas metodologias utilizam ambientes e exigem que os testes unitários sejam executados no ambiente de desenvolvimento (DEV) utilizando uma ferramenta para este proposito e reexecutados por consultores  funcionais/testadores, na fase de testes unitários no ambiente real de qualidade (QAS) para que só então possam executar a fase de testes integrados antes de aprovarem e homologarem o software para utilização em um ambiente produtivo (PRD).

O teste unitário executado do ponto de vista do setor de qualidade (QAS) é feito validando todas as partes dos software, incluindo, design intuitivo, usabilidade, teclas de atalho, layouts, grafia, links e etc. É claro que existem algumas diferenças sutis entre metodologias, como um ou outro procedimento ou diferentes nomenclaturas mas no final todas possuem o mesmo proposito, um software de qualidade, livre de erros e dentro do orçamento inicial do projeto. Bem! No mundo real, não importa qual a metodologia escolhida, isto nem sempre é possível.

PyCharm Community IDE

PyCharm é um ambiente profissional de desenvolvimento integrado (IDE) utilizado para a programação em Python. Ele fornece uma análise de código, depurador gráfico, testador unidade integrada, integração VCS/DVCS e apoia o desenvolvimento web com Django. Muitos desenvolvedores da comunidade Python elegeram o PyCharm como a melhor IDE para desenvolvimento Python, a IDE pode ser utilizada na versão comunitária ou na versão paga.

PyCharm: http://www.jetbrains.com/pycharm/

PyUnit – Unit Test Framework

O framework de testes unitários para Python, por vezes referido como PyUnit é uma versão da linguagem Python do JUnit. O JUnit é, por sua vez, uma versão Java do framework de testes Smalltalk, o JUnit é muito conhecido e utilizado no mudo Java também proliferou para outras linguagem de programação como entre outras, para C#.

PyUnit: https://docs.python.org/2/library/unittest.html

Executando Testes Unitários no PyCharm

1 – Crie um novo projeto Python chamado DAPyTeste, crie um novo arquivo Python chamado Participante e utilize o código encontrado logo abaixo. Na declaração da classe Participante clique com o botão direito e escolha Go To->Test:

Cria Classe de Teste

Cria Classe de Teste

2 – Para criar o teste escolha apenas os métodos Setters:

Métodos Setters

Métodos Setters

3 – Complete os métodos com respectivo código da classe de teste encontrado logo abaixo, utilize os comentários no código para saber mais sobre os teste unitários.

  • Para efetuar um teste com erros, modifique os valores alimentados nos métodos de teste.
  • Para rodar o teste na barra de ferramentas, selecione Unittests in DAPyTeste e clique em Run:
Erros

Erros

4 – Retorne os valores dos métodos como no código abaixo e execute o teste novamente:

Testes bem sucedidos

Testes bem sucedidos

 

Exemplo:

Neste exemplo criamos uma simples classe com métodos Getter e Setter e uma classe de caso de teste para efetuar um teste unitário nos métodos criados.

Python

Classe – Participante

# coding=utf-8
# Desenvolvimento Aberto
# Participante.py

__author__ = 'Desenvolvimento Aberto'

class Participante():

     # Define atributos privados
     def __init__(self):
         self.__nome = None
         self.__idade = None

     # Define métodos Getter e Setter
     def getNome(self):
         return self.__nome

     def setNome(self, nome):
         self.__nome = nome
         #Inverta o código acima: nome = self.nome
         #Você vai obter um erro de lógica
         #Passara pelo interpretador Python
         #Mas não passara pelo teste Unitário
         #Deste modo você previne erros escritos
         #por desatenção ou desenvolvimento emergências
         #como nos Sprints em algumas metodologias

     def getIdade(self):
         return self.__idade

     def setIdade(self, idade):
         self.__idade = idade

     # Você também pode optar por propriedades
     # Aos métodos Getter e Setter
     # Segue exemplo propriedade Nome:
     @property
     def Nome(self):
         return self.__nome

     @Nome.setter
     def Nome(self, value):
         self.__nome = value

# Cria Instancia da Classe
participante = Participante()

#Alimenta valores
participante.setNome("Joao da Silva")
participante.setIdade(20)

# Imprime dados
print participante.getNome()
print participante.getIdade()

PyUnit Test Case – ParticipanteTeste

# coding=utf-8
# Desenvolvimento Aberto
# TestParticipante.py

from unittest import TestCase
from Participante import Participante

__author__ = 'Desenvolvimento Aberto'

class TestParticipante(TestCase):

    # Define Métodos de Testes

    def test_setNome(self):
        # Testa métodos Getter e Setter
        p1 = Participante()
        p1.setNome("Nome")
        self.assertEqual("Nome", p1.getNome())

    def test_setIdade(self):
        # Testa métodos Getter e Setter
        p2 = Participante()
        p2.setIdade(20)
        self.assertEqual(20, p2.getIdade())

A maioria das metodologias disponíveis para o desenvolvimento de software e gerenciamento de projetos incluem como pratica básica essencial o desenvolvimento e execução de testes unitários para que um projeto de desenvolvimento possa passar para próxima fase.

Uma boa execução de um projeto bem elaborado em diversas metodologias utilizam ambientes e exigem que os testes unitários sejam executados no ambiente de desenvolvimento (DEV) utilizando uma ferramenta para este proposito e reexecutados por consultores  funcionais/testadores, na fase de testes unitários no ambiente real de qualidade (QAS) para que só então possam executar a fase de testes integrados antes de aprovarem e homologarem o software para utilização em um ambiente produtivo (PRD).

O teste unitário executado do ponto de vista do setor de qualidade (QAS) é feito validando todas as partes dos software, incluindo, design intuitivo, usabilidade, teclas de atalho, layouts, grafia, links e etc. É claro que existem algumas diferenças sutis entre metodologias, como um ou outro procedimento ou diferentes nomenclaturas mas no final todas possuem o mesmo proposito, um software de qualidade, livre de erros e dentro do orçamento inicial do projeto. Bem! No mundo real, não importa qual a metodologia escolhida, isto nem sempre é possível.

Microsoft Unit Test Framework for Managed Code

O framework de testes de unidade da Microsoft para código gerenciado é instalado com o Visual Studio e fornece um framework para testar o código .NET. As ferramentas de teste de unidade do Visual Studio foram desenvolvidas para oferecer suporte a desenvolvedores e equipes que incorporam testes unitários em suas práticas de desenvolvimento de software.  Testes de unidade proporcionam aos desenvolvedores e testadores uma maneira rápida para procurar erros de lógica nos métodos de classes em soluções .NET.

Unit Test Framework: http://msdn.microsoft.com/pt-br/library/dd264975.aspx

Executando Testes Unitários no Visual Studio

1 – Crie uma solução C# para o console chamada DATesteUnitario, renomeie o arquivo da classe gerado automaticamente de acordo com a classe do código Participante encontrado logo abaixo. Crie um novo projeto C# para teste chamado DATesteUnitarioTest nesta mesma solução:

Projeto - Test - C#

Projeto – Test – C#

2 – No Solution Explorer no projeto DATesteUnitarioTest adicione uma referencia ao projeto DATesteUnitario:

Adicionar Referencia

Adicionar Referencia

3 – Renomeie a classe criada automaticamente para o projeto de testes para ParticipanteTeste e utilize os métodos do código abaixo, atente-se aos comentários do código fonte para saber mais detalhes sobre os padrões de teste nos objetos C# no Visual Studio.

  • Para efetuar um teste com erros, modifique os valores alimentados na propriedade nome e idade nos métodos de teste.
  • Para rodar o teste, clique no menu Test e escolha a opção All Tests, o Visual Studio irá abrir uma janela chamada Test Explorer onde será exibido o resultado do teste de seus métodos:
Testes com Erros

Testes com Erros

4 – Retorne os valores das propriedades como no código abaixo, selecione os dois métodos com erros na janela Test Explorer e com o botão direito escolha a opção Run Selected Tests:

Testes bem Sucedidos

Testes bem Sucedidos

 

Exemplo:

Neste exemplo criamos uma simples classe com propriedades Get e Set e uma classe de caso de teste para efetuar um teste unitário nos métodos criados.

C#

Classe – Participante

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DATesteUnitario
{
    public class Participante
    {
        // Atributos da classe
        private string nome;
        private int idade;

        // Propriedades
        public string Nome {
            get
            {
                return nome;
            }
            set
            {
                 nome = value;
            }
        }

        public int Idade {
            get
            {
                return idade;
            }
            set
            {
               idade = value;
               // Troque a linha acima por: value = idade;
               // funciona na sintaxe mas não passa no teste unitário
               // pois é erro básico de logica e pode ser escrito em
               // um momento de desatenção.
            }
        }

        static void Main(string[] args)
        {
            // Testa classe
            // Dumb Code - Sem efeito para o teste
            Participante participante = new Participante();

            participante.Idade = 20;
            participante.Nome = "João da Silva";

            Console.ReadKey();
        }

    }
}

JUnit Test Case – ParticipanteTeste

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using DATesteUnitario; // Namespace do projeto a ser testado

namespace DATesteUnitarioTest
{
    [TestClass]
    public class ParticipanteTeste
    {
        /*          
         * Você pode optar por utilizar métodos Getter e Setter como Java (Bean).
         * Entretanto na linguagem C# métodos Getter e Setter são substituidos por
         * propriedades semelhantes a linguagem de programação Object Pascal (Delphi).
         *
         * O conceito de testes unitários é utilizado sempre através de métodos Setter (Voids)
         * pois o mesmo já testa o método de retorno Getter no momento da comparação.
         * Os métodos testados são os Construtores da classe, métodos Setter ou
         * outros métodos da classes de sua preferencia.
         *
         * O Caso de teste unitário do Projeto de Test C# é bem parecido com o JUnit para Java
         * utilizando o conceito de Assert e possui os seguintes requisitos:
         *
         * O método deve ser decorado com o atributo [TestMethod].
         * O método deve retornar void.
         * O método não pode ter parâmetros.
         *
         * Como testar um básico Pattern de Objeto C#
         * baseados em Get e Set (propriedades em C#)
         * utilizando voids?
         *
         * Podemos utilizar métodos semelhantes ao JUnit do Java, mas atente-se
         * pois diferentemente do JUnit a classe de teste não está fisicamente ligada
         * a classe a ser testada e utiliza uma void padrão.
         *
         * Método de teste padrão:

        [TestMethod]
        public void TestMethod1()
        {
        }

        */

        //Testando propriedades
         [TestMethod]
        public void Nome()
        {
             // Testa propriedade Nome
             Participante p1 = new Participante();
             p1.Nome = "Nome";
             Assert.AreEqual("Nome", p1.Nome);

        }

        [TestMethod]
        public void Idade()
         {
             // Testa propriedade Idade
             Participante p2 = new Participante();
             p2.Idade = 20;
             Assert.AreEqual(20, p2.Idade);
         }

    }
}

JUnit – Testes Unitários – Java

Publicado: 27 de novembro de 2014 em Java

A maioria das metodologias disponíveis para o desenvolvimento de software e gerenciamento de projetos incluem como pratica básica essencial o desenvolvimento e execução de testes unitários para que um projeto de desenvolvimento possa passar para próxima fase.

Uma boa execução de um projeto bem elaborado em diversas metodologias utilizam ambientes e exigem que os testes unitários sejam executados no ambiente de desenvolvimento (DEV) utilizando uma ferramenta para este proposito e reexecutados por consultores funcionais/testadores, na fase de testes unitários no ambiente real de qualidade (QAS) para que só então possam executar a fase de testes integrados antes de aprovarem e homologarem o software para utilização em um ambiente produtivo (PRD).

O teste unitário executado do ponto de vista do setor de qualidade (QAS) é feito validando todas as partes dos software, incluindo, design intuitivo, usabilidade, teclas de atalho, layouts, grafia, links e etc. É claro que existem algumas diferenças sutis entre metodologias, como um ou outro procedimento ou diferentes nomenclaturas mas no final todas possuem o mesmo proposito, um software de qualidade, livre de erros e dentro do orçamento inicial do projeto. Bem! No mundo real, não importa qual a metodologia escolhida, isto nem sempre é possível.

JUnit

O JUnit é um framework de código aberto, com suporte à criação de testes unitários para linguagem de programação Java. Esse framework facilita a criação de código para a automação de testes com apresentação dos resultados. Com ele, pode ser verificado se cada método de uma classe funciona da forma esperada, exibindo possíveis erros ou falhas.

JUnit: http://junit.org/

Executando Testes Unitários no Eclipse

1 – Crie um projeto Java SE no Eclipse e crie uma classe chamada de Participante dentro de um pacote chamado org.desenvolvimento.aberto. Utilize o código abaixo para preencher o código da classe que acabou de criar. Crie uma nova pasta chamada test para código escolhendo a opção: File->New->Source Foulder:

Source Folder

Source Folder

2 – Após criar a pasta de teste crie também o mesmo pacote para a pasta de teste:

Package

Package

3 – Clique com o botão direito em cima do pacote que acabou de criar e escolha a opção: New->JUnit Test Case. Defina o nome da classe como ParticipanteTeste e na opção Class Under Test escolha a classe Participante e clique em próximo:

JUnit Test Case

JUnit Test Case

4 – Para escolher os métodos da classe para teste sempre escolha somente os construtores da classe (caso haja construtores Overload) e os métodos Setters, não escolheremos os métodos Getters pois os utilizaremos para testar os métodos Setters no caso de teste:

Métodos para teste

Métodos para teste

5 – Após clicar em Finish, quando você utiliza o JUnit pela primeira vez você precisa adicionar a biblioteca do Framework JUnit no Build Path do Eclipse, você pode fazer isto de vários modos, o mais fácil é clicando em OK na próxima janela:

JUnit - Build Path

JUnit – Build Path

6 – Uma classe de testes foi criada para você com métodos ainda não implementados, no qual precisamos implementar para que possamos executar com sucesso os testes unitários. Na barra de ferramentas escolha Run As e clique na opção: JUnit Test:

Compilar Classe de Teste

Compilar Classe de Teste

7 – Como ainda não implementamos os métodos para garantir que nossa classe que está sobre testes tenha sucesso, vamos obter um erro na aba JUnit que aparecerá do lado esquerdo ao lado da aba de exploração do projeto:

JUnit - Erro

JUnit – Erro

8 – Para implementar os métodos de teste na classe de teste, precisamos instanciar o objeto da classe que será testada, alimentar um valor em seu método Setter e depois comparar o valor alimentado com o valor retornado pelo método Getter, deste modo confirmamos que todos os métodos do objeto sejam testado. Utilize o código abaixo para implementar sua classe de testes e compile novamente a classe de teste:

Teste Unitário - OK

Teste Unitário – OK

Exemplo:

Neste exemplo criamos uma simples classe com métodos Getters e Setters e uma classe de caso de teste para efetuar um teste unitário nos métodos criados.

Java

Classe – Participante

package org.desenvolvimento.aberto;

public class Participante {

	// Declara atributos da classe
	private String nome;
	private int idade;

	// Declara métodos Getter e Setter da classe
	public String getNome()
	{
		return nome;
	}

	public void setNome(String nome)
	{
		this.nome = nome;

          // Troque a linha acima por: nome = this.nome;
          // funciona na sintaxe mas não passa no teste unitário
          // pois é erro básico de logica e pode ser escrito em
          // um momento de desatenção.

	}

	public int getIdade()
	{
		return idade;
	}

	public void setIdade(int idade)
	{
		this.idade = idade;
	}

}

JUnit Test Case – ParticipanteTeste

package org.desenvolvimento.aberto;

import static org.junit.Assert.*;

import org.junit.Test;

public class ParticipanteTeste {

	@Test
	public void testSetNome()
	{
		// Implementa método de teste unitário: Nome
		Participante p1 = new Participante();
		p1.setNome("Jose");
		assertEquals("Jose", p1.getNome());
	}

	@Test
	public void testSetIdade()
	{
		// Implementa método de teste unitário: Idade
		Participante p2 = new Participante();
		p2.setIdade(20);
		assertEquals(20, p2.getIdade());
	}

}