Executando verificação de segurança...
-1

Pitch: Um framework de testes unitários simples (de verdade) para C, C++ e Objective-C

Fala, pessoal!

Quero compartilhar um projeto que eu desenvolvi porque… sinceramente, testar em C costuma ser mais irritante do que deveria.

O Cest é um framework de testes unitários header-only focado em ser direto ao ponto: sem dependências, sem configuração chata e sem API confusa.

A ideia aqui não é reinventar roda acadêmica — é só tornar testes em C algo minimamente agradável.

🚀 O que o Cest oferece hoje:

  • Header-only: só incluir o cest.h e usar
  • Zero dependências: nem -lm você precisa
  • Multi-linguagem real: C, C++, Objective-C e Objective-C++
  • API inspirada em Jest: describe, it, expect
  • Type-safe: usando _Generic (C) e overload (C++)
  • Output colorido: feedback visual direto no terminal
  • Suporte a múltiplos arquivos: estatísticas globais compartilhadas

👀 Exemplo simples:

Exemplo em C

#include "../cest.h"

static int add(int a, int b) { return a + b; }
static double divide(double a, double b) { return b != 0 ? a / b : 0; }

static int nums[] = {1, 2, 3};
static const char* strs[] = {"hello", "world"};

int main() {
    describe("C Basic Types", {
        it("should handle integers", {
            expect(2 + 2).toBe(4);
            expect(10 - 3).toEqual(7);
            expect(6 * 7).toEqual(42);
        });

        it("should handle floating point", {
            expect(3.14 + 0.86).toBeCloseTo(4.0, 0.001);
            expect(divide(10.0, 3.0)).toBeCloseTo(3.333, 0.001);
        });

        it("should handle booleans", {
            expect(true).toBeTruthy();
            expect(false).toBeFalsy();
            expect(1).toBeTruthy();
            expect(0).toBeFalsy();
        });

        it("should compare strings", {
            expect("hello").toEqual("hello");
            expect("world").toBe("world");
            expect("hello").toContain("ell");
        });

        it("should handle pointers", {
            int x = 42;
            expect(&x).toBeTruthy();
            expect((void*)NULL).toBeNull();
        });
    });

    describe("C Advanced", {
        it("should handle comparisons", {
            expect(10).toBeGreaterThan(5);
            expect(3).toBeLessThan(7);
        });

        it("should work with functions", {
            expect(add(2, 3)).toBe(5);
            expect(add(-1, 1)).toEqual(0);
        });

        it("should handle NULL pointers", {
            int* null_ptr = NULL;
            expect(null_ptr).toBeNull();
            expect(NULL).toBeFalsy();
        });

        it("should handle arrays", {
            expect(nums).toBeTruthy();
            expect(nums[0]).toEqual(1);
            expect(nums[1]).toEqual(2);
            expect(nums[2]).toEqual(3);
        });

        it("should handle string arrays", {
            expect(strs[0]).toEqual("hello");
            expect(strs[1]).toEqual("world");
        });
    });

    return cest_result();
}

Exemplo em Cpp

#include "../cest.h"
#include <vector>
#include <string>

int main() {
    describe("C++ Basic Types", {
        it("should handle integers", {
            expect(2 + 2).toBe(4);
            expect(10 - 3).toEqual(7);
        });

        it("should handle floating point", {
            expect(3.14 + 0.86).toBeCloseTo(4.0, 0.001);
        });

        it("should handle booleans", {
            expect(true).toBeTruthy();
            expect(false).toBeFalsy();
        });

        it("should handle std::string", {
            std::string s = "hello world";
            expect(s).toEqual("hello world");
            expect(s).toContain("world");
        });

        it("should handle pointers", {
            int x = 42;
            expect(&x).toBeTruthy();
            expect(static_cast<void*>(nullptr)).toBeNull();
        });
    });

    describe("C++ STL Containers", {
        it("should work with std::vector", {
            std::vector<int> v;
            v.push_back(1);
            v.push_back(2);
            v.push_back(3);
            expect(v.at(0)).toEqual(1);
            expect(v.at(1)).toEqual(2);
            expect(v.at(2)).toEqual(3);
        });

        it("should work with std::string concatenation", {
            std::string s1 = "hello";
            std::string s2 = "world";
            expect(s1 + " " + s2).toEqual("hello world");
        });
    });

    describe("C++ Type Inference", {
        it("should infer types correctly", {
            expect(3.14).toBeCloseTo(3.14, 0.001);
            expect(100).toEqual(100);
            expect(true).toBeTruthy();
        });
    });

    return cest_result();
}

Exemplo em ObjC

#import "../cest.h"

static int add_ints(int a, int b) { return a + b; }

int main() {
    describe("Objective-C Basic Types", {
        it("should handle integers", {
            expect(2 + 2).toBe(4);
            expect(10 - 3).toEqual(7);
        });

        it("should handle floating point", {
            expect(3.14 + 0.86).toBeCloseTo(4.0, 0.001);
        });

        it("should handle integers as bool", {
            expect(1).toBeTruthy();
            expect(0).toBeFalsy();
        });

        it("should handle pointers", {
            int x = 42;
            expect(&x).toBeTruthy();
            expect((void*)NULL).toBeNull();
        });

        it("should work with functions", {
            expect(add_ints(2, 3)).toBe(5);
            expect(add_ints(-1, 1)).toEqual(0);
        });
    });

    describe("Objective-C id Type", {
        it("should handle id type", {
            id obj1 = (id)0x1234;
            id obj2 = (id)0x1234;
            expect(obj1).toBe(obj2);
        });

        it("should handle nil", {
            id nil_obj = nil;
            expect(nil_obj).toBeNull();
            expect(nil_obj).toBeFalsy();
        });

        it("should work with id pointers", {
            id obj = (id)0x5678;
            expect(obj).toBeTruthy();
        });
    });

    return cest_result();
}

Exemplo em ObjCpp

#import "../cest.h"
#import <string>

static int add_ints(int a, int b) { return a + b; }

int main() {
    describe("Objective-C++ Basic Types", {
        it("should handle integers", {
            expect(2 + 2).toBe(4);
            expect(10 - 3).toEqual(7);
        });

        it("should handle floating point", {
            expect(3.14 + 0.86).toBeCloseTo(4.0, 0.001);
        });

        it("should handle integers as bool", {
            expect(1).toBeTruthy();
            expect(0).toBeFalsy();
        });

        it("should handle std::string", {
            std::string s = "hello world";
            expect(s).toEqual("hello world");
            expect(s).toContain("world");
        });

        it("should handle pointers", {
            int x = 42;
            expect(&x).toBeTruthy();
            expect(static_cast<void*>(nullptr)).toBeNull();
        });

        it("should work with functions", {
            expect(add_ints(2, 3)).toBe(5);
            expect(add_ints(-1, 1)).toEqual(0);
        });
    });

    describe("Objective-C++ id Type", {
        it("should handle id type", {
            id obj1 = (id)0x1234;
            id obj2 = (id)0x1234;
            expect(obj1).toBe(obj2);
        });

        it("should handle nil", {
            id nil_obj = nil;
            expect(nil_obj).toBeNull();
            expect(nil_obj).toBeFalsy();
        });

        it("should mix ObjC and C++ types", {
            id obj = (id)0x5678;
            std::string s = "mixed world";
            expect(obj).toBeTruthy();
            expect(s).toContain("world");
        });
    });

    return cest_result();
}

Sem boilerplate. Sem setup. Só escreve o teste e roda.

🛠️ Decisões técnicas (e possíveis pontos de crítica):

  • Uso de _Generic pra simular sobrecarga em C
  • Comparação de double com tolerância fixa (sim, dá pra discutir isso)
  • Sistema de matchers minimalista (sem macros absurdas ou reflection fake)
  • Compatibilidade com Objective-C incluindo id

🎯 Objetivo do projeto:

Ser algo que você adiciona no projeto e usa em 2 minutos — não um framework que exige onboarding.

Se não cumprir isso, falhou no propósito.

Se você já tentou testar algo em C e quase desistiu da vida, quero ouvir sua opinião.
Sem filtro — pode criticar mesmo

Carregando publicação patrocinada...