ABAP Unit Básico
📋 Visão Geral
ABAP Unit é o framework de testes unitários integrado ao SAP NetWeaver, permitindo criar testes automatizados diretamente no código ABAP.
🎯 O que é um Teste Unitário?
Um teste unitário verifica uma pequena parte do código (método, função) de forma isolada, garantindo que funciona conforme esperado.
Características: - ✅ Rápido (milissegundos) - ✅ Isolado (não depende de BD, sistema externo) - ✅ Repetível (sempre mesmo resultado) - ✅ Automatizado (executa sem intervenção)
🏗️ Anatomia de uma Classe de Teste
Estrutura Básica
*&---------------------------------------------------------------------*
*& Include ou Classe de Teste
*&---------------------------------------------------------------------*
CLASS ltc_my_test DEFINITION FOR TESTING
RISK LEVEL HARMLESS
DURATION SHORT.
PRIVATE SECTION.
DATA: mo_cut TYPE REF TO zcl_my_class. " Class Under Test
METHODS:
" Executado antes de CADA teste
setup,
" Testes (um método por cenário)
test_scenario_1 FOR TESTING,
test_scenario_2 FOR TESTING.
ENDCLASS.
CLASS ltc_my_test IMPLEMENTATION.
METHOD setup.
" Preparar ambiente
CREATE OBJECT mo_cut.
ENDMETHOD.
METHOD test_scenario_1.
" Arrange (preparar)
DATA(lv_input) = 'value'.
" Act (executar)
DATA(lv_result) = mo_cut->process( lv_input ).
" Assert (verificar)
cl_abap_unit_assert=>assert_equals(
act = lv_result
exp = 'expected'
msg = 'Resultado diferente do esperado' ).
ENDMETHOD.
METHOD test_scenario_2.
" Outro cenário de teste
ENDMETHOD.
ENDCLASS.
🏷️ Atributos de Teste
FOR TESTING
Marca método como teste:
METHODS test_add_numbers FOR TESTING.
RISK LEVEL
Indica risco se teste falhar:
CLASS ltc_test DEFINITION FOR TESTING
RISK LEVEL HARMLESS. " Sem risco
" ou
RISK LEVEL DANGEROUS. " Pode afetar dados
" ou
RISK LEVEL CRITICAL. " Pode causar danos graves
| Level | Uso |
|---|---|
| HARMLESS | Testes puros, sem efeitos colaterais |
| DANGEROUS | Pode gravar em BD, chamar RFCs |
| CRITICAL | Pode alterar customizing, master data |
DURATION
Tempo esperado de execução:
CLASS ltc_test DEFINITION FOR TESTING
DURATION SHORT. " < 1 minuto
" ou
DURATION MEDIUM. " 1-5 minutos
" ou
DURATION LONG. " > 5 minutos
Recomendação: Mantenha testes SHORT sempre que possível!
🎨 Padrão Arrange-Act-Assert (AAA)
Estrutura padrão para organizar testes:
METHOD test_calculate_discount.
" ═══ ARRANGE (Preparar) ═══
" Definir dados de entrada
DATA(lv_price) = 1000.
DATA(lv_discount_percent) = 10.
" ═══ ACT (Executar) ═══
" Chamar método sob teste
DATA(lv_final_price) = mo_cut->calculate_discount(
iv_price = lv_price
iv_discount = lv_discount_percent ).
" ═══ ASSERT (Verificar) ═══
" Validar resultado
cl_abap_unit_assert=>assert_equals(
act = lv_final_price
exp = 900
msg = |Desconto de { lv_discount_percent }% em { lv_price } deveria ser 900| ).
ENDMETHOD.
💡 Exemplo Completo: Calculadora
Classe a Testar
*&---------------------------------------------------------------------*
*& Classe: ZCL_CALCULATOR
*&---------------------------------------------------------------------*
CLASS zcl_calculator DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
METHODS:
add IMPORTING iv_a TYPE i
iv_b TYPE i
RETURNING VALUE(rv_result) TYPE i,
subtract IMPORTING iv_a TYPE i
iv_b TYPE i
RETURNING VALUE(rv_result) TYPE i,
divide IMPORTING iv_a TYPE i
iv_b TYPE i
RETURNING VALUE(rv_result) TYPE f
RAISING cx_sy_zerodivide.
ENDCLASS.
CLASS zcl_calculator IMPLEMENTATION.
METHOD add.
rv_result = iv_a + iv_b.
ENDMETHOD.
METHOD subtract.
rv_result = iv_a - iv_b.
ENDMETHOD.
METHOD divide.
IF iv_b = 0.
RAISE EXCEPTION TYPE cx_sy_zerodivide.
ENDIF.
rv_result = iv_a / iv_b.
ENDMETHOD.
ENDCLASS.
Classe de Teste
*&---------------------------------------------------------------------*
*& Testes: ZCL_CALCULATOR
*&---------------------------------------------------------------------*
CLASS ltc_calculator DEFINITION FOR TESTING
RISK LEVEL HARMLESS
DURATION SHORT.
PRIVATE SECTION.
DATA: mo_calculator TYPE REF TO zcl_calculator.
METHODS:
setup,
test_add_positive_numbers FOR TESTING,
test_add_negative_numbers FOR TESTING,
test_subtract FOR TESTING,
test_divide_normal FOR TESTING,
test_divide_by_zero FOR TESTING.
ENDCLASS.
CLASS ltc_calculator IMPLEMENTATION.
METHOD setup.
" Executado antes de CADA teste
CREATE OBJECT mo_calculator.
ENDMETHOD.
METHOD test_add_positive_numbers.
" Arrange
DATA(lv_a) = 5.
DATA(lv_b) = 3.
" Act
DATA(lv_result) = mo_calculator->add( iv_a = lv_a iv_b = lv_b ).
" Assert
cl_abap_unit_assert=>assert_equals(
act = lv_result
exp = 8
msg = '5 + 3 deveria ser 8' ).
ENDMETHOD.
METHOD test_add_negative_numbers.
" Arrange
DATA(lv_a) = -5.
DATA(lv_b) = 3.
" Act
DATA(lv_result) = mo_calculator->add( iv_a = lv_a iv_b = lv_b ).
" Assert
cl_abap_unit_assert=>assert_equals(
act = lv_result
exp = -2
msg = '-5 + 3 deveria ser -2' ).
ENDMETHOD.
METHOD test_subtract.
" Arrange
DATA(lv_a) = 10.
DATA(lv_b) = 4.
" Act
DATA(lv_result) = mo_calculator->subtract( iv_a = lv_a iv_b = lv_b ).
" Assert
cl_abap_unit_assert=>assert_equals(
act = lv_result
exp = 6
msg = '10 - 4 deveria ser 6' ).
ENDMETHOD.
METHOD test_divide_normal.
" Arrange
DATA(lv_a) = 10.
DATA(lv_b) = 2.
" Act
DATA(lv_result) = mo_calculator->divide( iv_a = lv_a iv_b = lv_b ).
" Assert
cl_abap_unit_assert=>assert_equals(
act = lv_result
exp = '5.0'
msg = '10 / 2 deveria ser 5.0' ).
ENDMETHOD.
METHOD test_divide_by_zero.
" Arrange
DATA(lv_a) = 10.
DATA(lv_b) = 0.
" Act & Assert (espera exceção)
TRY.
DATA(lv_result) = mo_calculator->divide( iv_a = lv_a iv_b = lv_b ).
" Se chegou aqui, não lançou exceção (FALHA!)
cl_abap_unit_assert=>fail(
msg = 'Deveria lançar exceção ao dividir por zero' ).
CATCH cx_sy_zerodivide.
" Sucesso! Exceção foi lançada como esperado
ENDTRY.
ENDMETHOD.
ENDCLASS.
▶️ Executar Testes
Eclipse ADT (Recomendado)
- Abrir classe no editor
- Ctrl+Shift+F10 - Executar testes
- Ver resultados na view "ABAP Unit"
Atalhos:
- Ctrl+Shift+F10 - Run Unit Tests
- Ctrl+Shift+F11 - Run with Coverage
- F5 - Re-run Last Test
SAP GUI
- SE80 ou SE24 - Abrir classe
- Classe → Executar → Testes Unitários (ou
F9) - Ver resultados na janela popup
📊 Interpretar Resultados
Testes Passando ✅
Run: 5 tests
Status: OK (Green)
Duration: 0.023s
Testes Falhando ❌
Run: 5 tests
Failed: 1
Duration: 0.031s
test_add_positive_numbers - FAILED
Expected: 8
Actual: 7
Message: 5 + 3 deveria ser 8
🎯 Onde Colocar Testes?
Opção 1: Test Include (Classes Globais)
ZCL_MY_CLASS
├── Definitions
├── Implementations
└── Test Classes (Include Automático)
Vantagem: Testes junto com código
Uso: Classes globais (SE24)
Opção 2: Include Separado (Reports)
*&---------------------------------------------------------------------*
*& Report Z_MY_REPORT
*&---------------------------------------------------------------------*
REPORT z_my_report.
" ... código do report ...
*&---------------------------------------------------------------------*
*& Test Include
*&---------------------------------------------------------------------*
INCLUDE z_my_report_test IF FOUND.
Arquivo: Z_MY_REPORT_TEST
CLASS ltc_test DEFINITION FOR TESTING ...
Opção 3: Classe de Teste Separada
" Classe principal: ZCL_ORDER_PROCESSOR
" Classe de teste: ZCL_ORDER_PROCESSOR_TEST (sufixo _TEST)
Uso: Testes muito complexos
⚡ Boas Práticas
✅ Fazer
" 1. Nomes descritivos
METHOD test_calculate_discount_returns_reduced_price.
" 2. Um assert por teste (ideal)
cl_abap_unit_assert=>assert_equals( act = lv_result exp = 100 ).
" 3. Sempre limpar em teardown
METHOD teardown.
CLEAR mo_cut.
" Deletar dados temporários
ENDMETHOD.
" 4. Testar casos extremos
METHOD test_add_max_integer.
" Testa limite superior
ENDMETHOD.
METHOD test_add_zero.
" Testa zero
ENDMETHOD.
" 5. Mensagens informativas
cl_abap_unit_assert=>assert_equals(
act = lv_count
exp = 5
msg = |Esperava 5 itens mas encontrou { lv_count }| ).
❌ Evitar
" 1. Nomes genéricos
METHOD test1. " ❌ Não diz o que testa
" 2. Muitas responsabilidades
METHOD test_everything.
" Testa 10 coisas diferentes ❌
ENDMETHOD.
" 3. Dependências externas
METHOD test_read_database.
SELECT * FROM kna1... " ❌ Não é teste unitário!
ENDMETHOD.
" 4. Sem assertions
METHOD test_process.
mo_cut->process( ). " ❌ Não verifica nada
ENDMETHOD.
" 5. Testes interdependentes
DATA: gv_shared_state. " ❌ Testes compartilhando estado
🔗 Próximos Passos
- Test Fixtures - Setup e teardown avançados
- Assertions - Todas as verificações disponíveis
- Test Doubles - Mockar dependências
Tags: #ABAP-Unit #Testing #Basics #AAA-Pattern