【问题标题】:Unit test for a C programC程序的单元测试
【发布时间】:2016-02-27 21:29:20
【问题描述】:

我有一个 C 程序,它可以提供质数到输入数。我想测试这个程序,看看它是否给出了合数。现在我需要实施测试,我觉得这很困难。因此,如果有人可以帮助我,我将不胜感激。

这是我的 Checkprime.c:

#include "defs.h"
#include "externs.h"
#include "minunit.h"

int CheckPrime(int K){

int J;

for (J=2; J*J <= K; J++){
  if (Prime[J] == 1){
     if (K % J == 0)  {
        Prime[K] = 0;
        return 0;
     }
   }

}   

Prime[K] = 1; 
return 1;
}

这是我的 main.c

#include <stdio.h>
#include "defs.h"
#include "checkprime.c"

int Prime[MaxPrimes]; 

int main()
{ 
int UpperBound;
int N;
int *ba = &UpperBound;

printf("enter upper bound\n");
scanf("%d",ba);

Prime[2] = 1;

for (N = 3; N <= *ba; N+= 2){
  CheckPrime(N);
  if (Prime[N]== 1) printf("%d is a prime\n",N);
 }
}

这是我的 minunit.c(测试,已实现):

#undef NDEBUG
#ifndef _minunit_h
#define _minunit_h

#include <stdio.h>
#include <stdlib.h>

#define mu_suite_start() char *message = NULL

#define mu_assert(test, message) if (!(test)) { return message; }
#define mu_run_test(test) \                 
message = test(); tests_run++; if (message) return message;

#define RUN_TESTS(name) int main(int argc, char *argv[]) {\
argc = 1; \
    printf("----\nRUNNING: %s\n", argv[0]);\
    char *result = name();\
    if (result != 0) {\
        printf("FAILED: %s\n", result);\
    }\
    else {\
        printf("ALL TESTS PASSED\n");\
    }\
printf("Tests run: %d\n", tests_run);\
    exit(result != 0);\
}

int tests_run;

#endif

我在互联网上找到了 minunit.c,但我不知道如何实现我想要的测试,并让它工作。我的目标是为我的程序做一个简单的测试。

【问题讨论】:

  • 没有什么能阻止Prime[J] 访问过去的Prime[MaxPrimes]
  • 这会阻止我进行单元测试吗?
  • 不检查 J 范围并不妨碍进行单元测试。它会阻止单元测试正常工作。运行代码并输入2147483647-2147483648 并查看单元测试检测到任何问题。
  • 嗯,好的,我会改变它,并将限制设置为 100 :) 但是单元测试呢?

标签: c unit-testing


【解决方案1】:

归根结底,测试只不过是一些代码,它会运行您的代码并检查您的假设是否正确。当你开始时,保持简单。不要使用测试框架,而是从 assert() 开始。

您可以通过以下方式测试CheckPrime()

#include <assert.h>
#include "checkprime.h"

void test_CheckPrime_primes() {
    int primes[] = {
        2, 3, 5, 7, 11, 13, 0
    };

    for( int idx = 0; primes[idx] != 0; idx++ ) {
        assert( CheckPrime(primes[idx]) );
    }
}

void test_CheckPrime_composites() {
    int composites[] = {
        1, 4, 6, 8, 9, 10, 12, 14, 0
    };

    for( int idx = 0; composites[idx] != 0; idx++ ) {
        assert( !CheckPrime(composites[idx]) );
    }
}

int main() {
    test_CheckPrime_primes();
    test_CheckPrime_composites();

    return 0;
}

这个简单的测试程序将揭示使用CheckPrime() 的问题。最大的两个是它没有头文件,Primes 必须由调用者初始化。它还将允许您了解要编写什么样的断言。例如,0 会发生什么? 1? -1? INT_MAX?比您的 Primes 数组更大的候选人?

一旦您掌握了基础知识并了解了测试的全部内容,assert() 可以替换为 more informative assertstesting framework

【讨论】:

  • 基本上:你怎么知道测试制度是准确的。导致无限回归。
  • 使用框架不是更好吗?这是我在网上看到的
  • @Nasc 是的。但是在学习测试时,一个复杂的框架可能会妨碍测试,使测试看起来非常复杂,尤其是在 C 中。你的有一些毛茸茸的宏。了解使用普通程序进行测试、调用普通库以及使用assertprintf 的概念。然后选择一个框架。
  • @ArifBurhan 新手总是担心这一点,但很少会在代码中犯错误和在测试中犯错误,以至于他们排队等于通过测试。测试永远不能证明代码没有错误,它只能证明它没有你认为要测试的错误。是风险管理。仅仅因为你不能将错误的风险降低到零并不意味着你不应该显着降低风险。然而,讨论单元测试的实用性并不是这个问题的目的。
【解决方案2】:

这是我的 minunit.c ...

我猜你的意思是minunit.h。鉴于此,您可以像 mu_checkprime.c 一样实现测试:

#include "checkprime.c"

int Prime[MaxPrimes]; 

static char *test_primes()
{
    mu_assert(CheckPrime(2) == 1,   "2 not found to be prime");
    mu_assert(CheckPrime(3) == 1,   "3 not found to be prime");
    mu_assert(CheckPrime(5) == 1,   "5 not found to be prime");
    mu_assert(CheckPrime(7) == 1,   "7 not found to be prime");
    mu_assert(CheckPrime(11) == 1, "11 not found to be prime");
    mu_assert(CheckPrime(13) == 1, "13 not found to be prime");
    return 0;
}

static char *test_composites()
{
    mu_assert(CheckPrime(1) == 0,   "1 found to be prime");
    mu_assert(CheckPrime(4) == 0,   "4 found to be prime");
    mu_assert(CheckPrime(6) == 0,   "6 found to be prime");
    mu_assert(CheckPrime(8) == 0,   "8 found to be prime");
    mu_assert(CheckPrime(9) == 0,   "9 found to be prime");
    mu_assert(CheckPrime(10) == 0, "10 found to be prime");
    mu_assert(CheckPrime(12) == 0, "12 found to be prime");
    mu_assert(CheckPrime(14) == 0, "14 found to be prime");
    return 0;
}

static char *all_tests()
{
     mu_suite_start();
     mu_run_test(test_primes);
     mu_run_test(test_composites);
     return 0;
}

RUN_TESTS(all_tests)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-21
    • 1970-01-01
    • 2018-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-09
    • 1970-01-01
    相关资源
    最近更新 更多