テストコードの書き方、

# テストコードの良い書き方。

テストコードで得られる情報は非常に重要であり、テストコードを書くことにより、そのシステムの品質が上がります。

しかしテストコードの書き方を複雑に書き過ぎると、良いテストコードとは言えません。

下記に記したものは、 ユニークでランダムな数値の配列を作成する関数と、そのランダムな配列がユニークかつ、ランダムになってるかのテストである、

```
/*
 * Create ordered array
 *
 */
-(NSMutableArray*)insertNumber:(NSInteger)number{
    NSMutableArray* array = [NSMutableArray array];
    for(NSInteger i = 0; i<number;i++){
        [array addObject:[NSNumber numberWithInteger:i]];
    }
    return array;
}

/*
 * create Random Array
 */
-(NSArray *)randomArray:(NSArray *)array{
    NSMutableArray* ary = array.mutableCopy;
    for(NSInteger n = 0; n < array.count;n++){
        NSInteger random = arc4random() % array.count;
        [ary exchangeObjectAtIndex:n withObjectAtIndex:random];
    }
    return ary.mutableCopy;
}


/*
 *
 * TEST CODE
 *
 */
-(void)TEST{
    
    __block NSInteger num = 0;
    __block BOOL isBUSTED = NO;
    
    for(;num<TEST_COUNT_NUMBER;){
        
        __block NSArray* random = [self randomArray:[self insertNumber:3]];
        
        [self TESTCODE:random TESTVal:^(NSInteger i, NSInteger n,NSInteger same) {
            
            if([random[i]integerValue] == [random[n]integerValue]){
                same++;
                if(same==2){
                    isBUSTED = YES;
                
                }
            }
            
            if(isBUSTED)
                printf("\n BUSTED  Failuer \n");
                
            if(i>=(random.count-1) && n>=(random.count-1)){
                num++;
                printf("COMPLETION %ld TIME TEST\n",num);
            }
        }];
        
    }
    printf("\nCompletion\n\n");
}

/*
 * TEST CODE
 *
 */
-(void)TESTCODE:(NSArray*)ary
        TESTVal:(void (^)(NSInteger i,NSInteger n,NSInteger same))handler{
    
    NSInteger count = 0;
    
    for(NSInteger i=0;i<ary.count;i++){
        count = 0;
        for(NSInteger n = 0;n<ary.count;n++){
            handler(i,n,count);
        }
    }
}

```
main.m

```
#import <Foundation/Foundation.h>
#import "Random.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        [[Random new]TEST];
    }
    return 0;
}
```

このテストコードは最悪である、まずわかりづらい、複雑であり解析が容易ではなく、そしてバグの温床になるコードで拡張性が低いと言えると思われる。


このようなテストコードは書くべきでない、


こちらのコードをリファクタリングしたものが下記である。

```

/*
 *
 * TEST CODE
 *
 */
-(BOOL) TEST_RANDOM:(NSArray*)ary {
    BOOL isUnique = NO;
    for(NSInteger base = 0; base < ary.count; base++){
        int count = 0;
        for(NSInteger locate = 0; locate < ary.count; locate++ ){
            if([ary[base]integerValue]==[ary[locate]integerValue]){
                count++;
                if(count==2){
                    isUnique = YES;
                }
            }
        }
    }
    return isUnique;
}

/*
 * New TEST CODE
 *
 */
-(void) TEST_RANDOM {
    
    for ( NSInteger num = 0; num < TEST_COUNT_NUMBER; num++ ){
        
        NSArray* numbers = [self insertNumber:30];
     
        NSArray* randoms = [self randomArray:numbers];
        
        if( [self TEST_RANDOM:randoms] == YES ){
            
            NSLog(@"Failuer Not unique and Random");
            
        }
    }
}


```

こちらのテストコードはわかりやすくかかれてるといえる、

配列内の数値を全て走査しユニークかのテストを行なっている。

この書き方だと、拡張性が高く、管理がしやすく、何が書いてあるのか一目瞭然である。

今回の記事で使ったコードは下記に記しておきました。

https://gist.github.com/keisukeYamagishi/331ae9f09d4ea5314bdc12ea3125f2b8

以上