Ir para o conteúdo

Assertions

📋 Visão Geral

Assertions são verificações que determinam se um teste passou ou falhou. Classe cl_abap_unit_assert fornece métodos estáticos para validar resultados.


✅ Assertions Principais

assert_equals

Verifica se dois valores são iguais.

cl_abap_unit_assert=>assert_equals(
  act = lv_resultado     " Valor atual
  exp = lv_esperado      " Valor esperado
  msg = 'Mensagem de erro se falhar' ).

" Exemplo
DATA(lv_soma) = 5 + 3.

cl_abap_unit_assert=>assert_equals(
  act = lv_soma
  exp = 8
  msg = '5 + 3 deveria ser 8' ).

assert_not_equals

Verifica se dois valores são diferentes.

cl_abap_unit_assert=>assert_not_equals(
  act = lv_new_id
  exp = lv_old_id
  msg = 'Novo ID deveria ser diferente do antigo' ).

assert_true / assert_false

Verifica condição booleana.

" assert_true
cl_abap_unit_assert=>assert_true(
  act = lv_is_valid
  msg = 'Validação deveria retornar true' ).

" assert_false
cl_abap_unit_assert=>assert_false(
  act = lv_has_errors
  msg = 'Não deveria ter erros' ).

assert_initial / assert_not_initial

Verifica se variável está vazia ou preenchida.

" assert_initial (vazio)
cl_abap_unit_assert=>assert_initial(
  act = lv_result
  msg = 'Resultado deveria estar vazio' ).

" assert_not_initial (preenchido)
cl_abap_unit_assert=>assert_not_initial(
  act = lv_customer_id
  msg = 'Customer ID não deveria estar vazio' ).

assert_bound / assert_not_bound

Verifica se referência está atribuída.

" assert_bound (objeto existe)
cl_abap_unit_assert=>assert_bound(
  act = mo_processor
  msg = 'Objeto deveria estar criado' ).

" assert_not_bound (objeto não existe)
cl_abap_unit_assert=>assert_not_bound(
  act = mo_connection
  msg = 'Conexão não deveria estar ativa' ).

assert_subrc

Verifica sy-subrc.

SELECT SINGLE * FROM kna1
  WHERE kunnr = lv_customer
  INTO @DATA(ls_customer).

cl_abap_unit_assert=>assert_subrc(
  act = sy-subrc
  exp = 0
  msg = |Cliente { lv_customer } deveria existir| ).

assert_table_contains

Verifica se tabela contém linha específica.

cl_abap_unit_assert=>assert_table_contains(
  line  = VALUE ty_customer( kunnr = '100001' name1 = 'Test' )
  table = lt_customers
  msg   = 'Cliente de teste deveria estar na tabela' ).

assert_differs

Verifica se valores são fisicamente diferentes (não apenas conteúdo).

DATA: lv_ref1 TYPE REF TO data,
      lv_ref2 TYPE REF TO data.

CREATE DATA lv_ref1.
CREATE DATA lv_ref2.

cl_abap_unit_assert=>assert_differs(
  act = lv_ref1
  exp = lv_ref2
  msg = 'Deveriam ser referências diferentes' ).

🚨 fail()

Forçar falha do teste.

IF lv_error_occurred = abap_true.
  cl_abap_unit_assert=>fail(
    msg = 'Operação não deveria ter falhado' ).
ENDIF.

" Uso comum: verificar se exceção foi lançada
TRY.
    mo_cut->dangerous_operation( ).

    " Se chegou aqui, não lançou exceção = FALHA
    cl_abap_unit_assert=>fail(
      msg = 'Deveria ter lançado exceção' ).

  CATCH cx_custom_error.
    " OK - exceção foi lançada
ENDTRY.

💡 Exemplos Práticos

Teste com Múltiplas Assertions

METHOD test_create_order.
  " Arrange
  DATA(lv_customer) = '100001'.

  " Act
  DATA(ls_order) = mo_cut->create_order(
    iv_customer = lv_customer
    iv_material = 'MAT001'
    iv_quantity = 10 ).

  " Assert - múltiplas verificações
  cl_abap_unit_assert=>assert_not_initial(
    act = ls_order-vbeln
    msg = 'Order ID deveria ser gerado' ).

  cl_abap_unit_assert=>assert_equals(
    act = ls_order-kunnr
    exp = lv_customer
    msg = 'Customer deveria ser o mesmo' ).

  cl_abap_unit_assert=>assert_equals(
    act = ls_order-status
    exp = 'NEW'
    msg = 'Status inicial deveria ser NEW' ).

  cl_abap_unit_assert=>assert_true(
    act = xsdbool( ls_order-netwr > 0 )
    msg = 'Valor líquido deveria ser maior que zero' ).
ENDMETHOD.

Testar Exceções

METHOD test_divide_by_zero_raises_exception.
  " Arrange
  DATA(lv_a) = 10.
  DATA(lv_b) = 0.

  " Act & Assert
  TRY.
      DATA(lv_result) = mo_calculator->divide( iv_a = lv_a iv_b = lv_b ).

      " Se chegou aqui = FALHA
      cl_abap_unit_assert=>fail(
        msg = 'Deveria lançar cx_sy_zerodivide' ).

    CATCH cx_sy_zerodivide.
      " Sucesso! Exceção esperada foi lançada
  ENDTRY.
ENDMETHOD.

Testar Tabelas

METHOD test_filter_returns_correct_items.
  " Arrange
  DATA(lt_input) = VALUE ty_items_tab(
    ( id = '1' status = 'ACTIVE' )
    ( id = '2' status = 'INACTIVE' )
    ( id = '3' status = 'ACTIVE' )
  ).

  " Act
  DATA(lt_result) = mo_cut->filter_active( lt_input ).

  " Assert
  cl_abap_unit_assert=>assert_equals(
    act = lines( lt_result )
    exp = 2
    msg = 'Deveria retornar 2 itens ativos' ).

  " Verificar conteúdo
  cl_abap_unit_assert=>assert_table_contains(
    line  = VALUE ty_item( id = '1' status = 'ACTIVE' )
    table = lt_result
    msg   = 'Deveria conter item 1' ).

  cl_abap_unit_assert=>assert_table_contains(
    line  = VALUE ty_item( id = '3' status = 'ACTIVE' )
    table = lt_result
    msg   = 'Deveria conter item 3' ).
ENDMETHOD.

Comparar Estruturas

METHOD test_calculate_returns_correct_structure.
  " Arrange
  DATA(lv_price) = 1000.
  DATA(lv_tax_rate) = '0.23'.

  " Act
  DATA(ls_result) = mo_cut->calculate_with_tax(
    iv_price    = lv_price
    iv_tax_rate = lv_tax_rate ).

  " Assert - estrutura esperada
  DATA(ls_expected) = VALUE ty_result(
    net_price   = 1000
    tax_amount  = 230
    gross_price = 1230
    currency    = 'EUR' ).

  cl_abap_unit_assert=>assert_equals(
    act = ls_result
    exp = ls_expected
    msg = 'Cálculo deveria retornar estrutura correta' ).
ENDMETHOD.

📊 Tabela de Assertions

Assertion Uso Exemplo
assert_equals Igualdade act = 8, exp = 8
assert_not_equals Diferença act = 'A', exp = 'B'
assert_true Condição verdadeira act = abap_true
assert_false Condição falsa act = abap_false
assert_initial Valor vazio act = ''
assert_not_initial Valor preenchido act = 'XYZ'
assert_bound Objeto existe act = mo_obj
assert_not_bound Objeto não existe act = mo_null
assert_subrc sy-subrc act = 0, exp = 0
assert_table_contains Linha em tabela line in table
assert_differs Referências diferentes ref1 <> ref2
fail Forçar falha Quando condição inesperada

⚡ Boas Práticas

✅ Fazer

" 1. Mensagens descritivas
cl_abap_unit_assert=>assert_equals(
  act = lv_count
  exp = 5
  msg = |Esperava 5 itens mas encontrou { lv_count }| ).  " ✅

" 2. Um conceito por teste
METHOD test_add_returns_sum.
  " ✅ Testa APENAS soma
  cl_abap_unit_assert=>assert_equals( act = lv_result exp = 8 ).
ENDMETHOD.

" 3. Valores esperados explícitos
cl_abap_unit_assert=>assert_equals(
  act = ls_order-status
  exp = 'APPROVED' ).  " ✅ Literal claro

" 4. assert_true para condições complexas
cl_abap_unit_assert=>assert_true(
  act = xsdbool( lv_date BETWEEN '20250101' AND '20251231' )
  msg = 'Data deveria estar em 2025' ).  " ✅

❌ Evitar

" 1. Mensagens genéricas
cl_abap_unit_assert=>assert_equals(
  act = lv_result
  exp = 8
  msg = 'Erro' ).  " ❌ Não ajuda a debugar

" 2. Múltiplos conceitos num teste
METHOD test_everything.
  cl_abap_unit_assert=>assert_equals( ... ).  " Testa A
  cl_abap_unit_assert=>assert_true( ... ).    " Testa B
  cl_abap_unit_assert=>assert_bound( ... ).   " Testa C
  " ❌ Difícil saber o que falhou
ENDMETHOD.

" 3. Calcular valor esperado
DATA(lv_expected) = lv_input * 2 + 5.  " ❌ Pode ter mesmo bug
cl_abap_unit_assert=>assert_equals(
  act = mo_cut->calculate( lv_input )
  exp = lv_expected ).

" 4. Testes sem assertions
METHOD test_process.
  mo_cut->process( ).  " ❌ Não verifica nada!
ENDMETHOD.

🎯 Assertions Customizadas

Criar assertions próprias para reutilização:

CLASS lcl_custom_assert DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS:
      assert_order_valid
        IMPORTING is_order TYPE ty_order
        RAISING   cx_static_check.
ENDCLASS.

CLASS lcl_custom_assert IMPLEMENTATION.
  METHOD assert_order_valid.
    cl_abap_unit_assert=>assert_not_initial(
      act = is_order-vbeln
      msg = 'Order ID é obrigatório' ).

    cl_abap_unit_assert=>assert_not_initial(
      act = is_order-kunnr
      msg = 'Customer é obrigatório' ).

    cl_abap_unit_assert=>assert_true(
      act = xsdbool( is_order-netwr > 0 )
      msg = 'Valor deve ser maior que zero' ).
  ENDMETHOD.
ENDCLASS.

" Uso
METHOD test_create_order.
  DATA(ls_order) = mo_cut->create( ... ).
  lcl_custom_assert=>assert_order_valid( ls_order ).  " ✅ Reutilizável
ENDMETHOD.

🔗 Próximos Passos


Tags: #Assertions #Verification #Testing #ABAP-Unit