2022.01.31 ~ 02.04


01.31月


参考講座-白奇仙のJavaとアプリケーションをテストする様々な方法

▼▼▼JUnitテスト例


JUnitはテスト順序を決定していないため、各テストメソッドは新しいクラスインスタンスを作成して実行します(ハッシュ値でチェックすると、異なるインスタンスが見つかります)->依存性を低減します.
JUnit 5に変更メソッドが作成されました
各クラスのインスタンスを作成して共有
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class StudyTest {

	// 클래스당 테스트 인스턴스를 만들면 static일 필요 없음
	@BeforeAll
	void beforeall() {System.out.println("before all");}

    int value = 1;
    
    @FastTest
    @DisplayName("스터디 만들기 fast")
    void create_new_study() {
        System.out.println(value++);
        Study actual = new Study(value++);
    }
}
  • JUnitテストメソッドごとに新しいテストインスタンスを作成
  • 基本戦略
  • 試験方法とは独立して、
  • は予期せぬ副作用を回避することができる.
  • このポリシーをJUnit 5で変更できる
  • @TestInstance(Lifecycle.PER_CLASS)
  • 各テストクラスは、
  • を使用して1つのインスタンスのみを作成します.
  • の場合、@BeforeEachまたは@AfterEachでテスト間で共有されるすべての状態を初期化する必要があります.
  • @Beforealおよび@AfterAllは、インスタンスメソッドまたはインタフェースで定義されたデフォルトメソッドとして定義することもできます.
  • ▼▼試験手順


    試験手順には内部規定の手順がありますただし、順序は内部構成ロジックによって変更される可能性がありますので、この順序に依存してはいけません.
    正しいユニットテストを作成した場合は、他のユニットテストとは独立して実行できる必要があります->相互に依存しない->順序はに依存できません.
    しかし、場合によっては、テストスキームなど...インスタンスを作成して共有する必要があります
    特定の順序でテストを実行する場合は、@TestMethodOrderと@TestInstance(Lifecycle.PER CLASS)を使用してテスト方法を実行できます.
    構成
  • メソッドOrder実装体
  • 基本インプリメンテーション
  • Alphanumeric
  • OrderAnnoation
  • Random
  • @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
    @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
    class StudyTest {
    
        int value = 1;
    
        @Order(2)
        @FastTest
        @DisplayName("스터디 만들기 fast")
        void create_new_study() {
            System.out.println(value++);
            Study actual = new Study(value++); // 항상 1임 -> 테스트 매서드마다 클래스 인스턴스를 새로 만들기 때문 -> 테스트 마다 의존성을 줄이기 위해
        }
    
        @Order(1)
        @Test
        @DisplayName("스터디 만들기 slow")
        @Tag("slow")
        void create_new_study_again() {
            System.out.println("create1");
        }
    
    }
    slowはfastより先に実行

    ✏️ junit-platform.properties


    クラスパス(src/test/resources/)に適用されるJUnitプロファイル.
    テストインスタンスのライフサイクルの設定
    junit.jupiter.testinstance.lifecycle.default = per_class
    拡張パッケージ自動検出機能
    junit.jupiter.extensions.autodetection.enabled = true
    @Disabledを無視して実行
    junit.jupiter.conditions.deactivate = org.junit.*DisabledCondition
    テストネーミングポリシーの設定
    junit.jupiter.displayname.generator.default =\
    org.junit.jupiter.api.DisplayNameGenerator$ReplaceUnderscores

    02.01話


    参考講座-白奇仙のJavaとアプリケーションをテストする様々な方法

    Monckitoの概要

  • Mock:実際のオブジェクトと似ていますが、プログラマがその動作を管理するオブジェクトです.
  • Mockito:Mockオブジェクトを簡単に作成、管理、検証する方法を提供します.

  • Mockitoオブジェクトの作成


    Spring-boot-start-testにMockitoを自動的に追加
    Mockito特定のクラスまたはインタフェースのダミーオブジェクトを作成
    以下の3点さえ分かれば,モジュールを用いたテストを容易に記述できる.
    (1)Mockの作成方法
    (2)ブロックがどのように動作するかを管理する方法
    (3)Mock挙動の検証方法

    Mockito.mock()メソッドの作成方法

    MemberService memberService = mock(MemberService.class);
    StudyRepository studyRepository = mock(StudyRepository.class);
    

    @Mockアニメーションの作成方法

  • JUnit 5拡張としてMockito Extensionを使用する必要があります.
  • フィールド
  • メソッドパラメータ
  • @ExtendWith(MockitoExtension.class)
    class StudyServiceTest {
    
        @Mock MemberService memberService;
    
        @Mock StudyRepository studyRepository;
    
    サンプルコード
    @ExtendWith(MockitoExtension.class)
    class StudyServiceTest {
        
        @Test
        void createStudyService(@Mock MemberService memberservice, @Mock StudyRepository studyRepository) {
    
            Optional<Member> optional = memberService.findById(1L);
            
    
            StudyService studyService = new StudyService(memberService, studyRepository);
            assertNotNull(studyService);
        }
    }

    ▼▼MockオブジェクトStubbing

    @ExtendWith(MockitoExtension.class)
    class StudyServiceTest {
        
        @Test
        void createStudyService(@Mock MemberService memberservice, @Mock StudyRepository studyRepository) {
    
            StudyService studyService = new StudyService(memberService, studyRepository);
            assertNotNull(studyService);
    
            Member member = new Member();
            member.setId(1L);
            member.setEmail("[email protected]");
    
            when(memberService.findById(1L)).thenReturn(Optional.of(member));
    
            Study study = new Study(10, "java");
    
            Optional<Member> findById = memberService.findById(1L);
            assertEquals("[email protected]", findById.get().getEmail());
    
            //studyService.createNewStudy(1L, study);
        }
    }

    すべてのMockオブジェクトの動作


    は、
  • Nullを返します.(オプションタイプはOptional.empty return)
  • PrimitiveタイプのデフォルトPrimitive値は
  • です.
  • コレクションは空のコレクション
  • です.
  • Voidメソッドは例外ではなく、何も起こりません.
  • Mockオブジェクトを操作することで
  • あるパラメータを受信と、ある値を異常
  • に戻す又は投げ出すことができる.
  • Voidメソッドは、特定のパラメータを受信または呼び出すときに異常が発生する可能性がある
  • .
    同じパラメータが複数回呼び出されたときの
  • メソッドの動作を操作できます.

    BDDスタイルAPI


    BDD
    :これはTDDが作成したアプリケーションがどのように「行動」すべきかを共通認識する方法です.

    動作仕様

  • Title
  • Narrative
  • - As a/ I want /so that
  • Acceptance criteria
  • Given/When/Then
  • Mockitoは、BddMockitoというクラスを介して、BDDスタイルのAPIを提供する.
    When -> Given
    given(memberService.findById(1L)).willReturn(Optional.of(member));
    given(studyRepository.save(study)).willReturn(study);
    
    Verify -> Then
    then(memberService).should(times(1)).notify(study);
    then(memberService).shouldHaveNoMoreInteractions();
    

    02.02数量


    アルゴリズムの基本問題から強固に~~!

    ▼▼Ramda関数


    Ramda関数とは?これは匿名関数です.
    基本関数とランダコードの使用例を比較してみましょう

    関数として作成

    def plus_one(x):
    	return x + 1
    
    print(plus_one(1))

    ランダを利用

    plus_two = lambda x: x+2
    print(plus_two(1))
    Ramda関数は内蔵関数のパラメータとして非常に有効です
    ->通常sort()に使用されます

    例)

    def plus_one(x):
    	return x + 1
    
    a[1, 2, 3]
    print(list(map(plus_one, a)))
    
    # 람다 활용
    print(list(map(lambda x: x+1, a)))

    ✏️ round()


    python丸め関数round()はround half偶数方式を採用する.
    ->round half ever=近似値を偶数に設定します.
    ->round half up=0.5以上なら大数四捨五入.
    a = 4.500
    print(round(a)) // 4 출력
    
    a = 4.5111
    print(round(a)) // 5 출력
    
    a = 5.5000
    print(round(a)) // 6 출력
    

    解決策


    簡単に0.5を足してintに変えればいいです
    a = 67.5
    a = a + 0.5
    a = int(a)
    print(a)
    

    ▼▼▼例


    簡単な問題を解いてみましょう.

    1-1. K番目の約数

    from sys import stdin
    
    n, k = map(int, stdin.readline().split())
    
    cnt = 0
    for i in range(1, n+1):
        if n % i == 0:
            cnt += 1
        if cnt == k:
            print(i)
            break
    
    else:
        print(-1)

    1-2. K番目の数

    # K번째 수
    from sys import stdin
    
    T = int(stdin.readline())
    
    for t in range(T):
        n, s, e, k = map(int, stdin.readline().split())
        nums = list(map(int, stdin.readline().split()))
        nums = nums[s-1:e]
        nums.sort()
        print("#%d %d" %(t+1, nums[k-1]))

    1-3. K次大数

    # K번째 큰 수
    from sys import stdin
    
    n, k = map(int, stdin.readline().split())
    cards = list(map(int, stdin.readline().split()))
    
    res = set() 
    
    for i in range(n):
        for j in range(i+1, n):
            for m in range(j+1, n):
                res.add(cards[i] + cards[j] + cards[m])
    
    res = list(res)
    res.sort(reverse=True)
    
    print(res[k-1])

    1-4. 代表価格

  • の列挙()は、リスト内のインデックス値と実際の値とを対応付ける方法
  • である.
    from sys import stdin
    
    n = int(stdin.readline())
    a = list(map(int, stdin.readline().split()))
    ave = round(sum(a)/n)
    
    min = 2147000000
    
    for idx, x in enumerate(a):
        tmp = abs(x - ave)
        if tmp < min:
            min = tmp
            score = x
            res = idx + 1
        elif tmp == min:
            if x > score:
                score = x
                res = idx + 1
    
    print(ave, res)

    1-5. せいためんたい

    from sys import stdin
    
    n, m = map(int, stdin.readline())
    cnt = [0] * (n+m+3)
    max = -2147000000
    
    for i in range(1, n+1):
        for j in range(1, m+1):
            cnt[i+j] += 1
    
    for i in range(n+m+1):
        if cnt[i] > max:
            max = cnt[i]
    
    for i in range(n+m+1):
        if cnt[i] == max:
            print(i, end=' ')

    1-6. 桁数の和

    from sys import stdin
    
    n = int(stdin.readline())
    a = list(map(int, stdin.readline().split()))
    
    # def digit_sum(x):
    #     sum = 0
    #     while x > 0:
    #         sum += x%10
    #         x = x//10
    
    def digit_sum(x):
        sum = 0
        for i in str(x):
            sum += int(i)
        return sum
        
    max = -2147000000
    
    for x in a:
        total = digit_sum(x)
        if total > max:
            max = total
            res = x
    
    print(res)

    ▼▼▼▼テストステロン


    ふるい=フィルタ形式で2からnまでドアの周りを回り、このi個の数の倍数にアクセスすることでこれらの倍数をフィルタリングする(=少数しか得られない)
    from sys import stdin
    
    n = int(stdin.readline())
    ch = [0] * (n+1)
    cnt = 0
    for i in range(2, n+1):
        if ch[i] == 0:
            cnt += 1
            for j in range(i, n+1, i):
                ch[j] = 1
    
    print(cnt)

    ▼▼▼▼反転小数


    ...自然数が少数であるか否かを判別する問題.
    # 뒤집은 소수
    from sys import stdin
    
    def reverse(x):
        res = 0
        while x > 0:
            t = x % 10
            res = res * 10 + t
            x = x // 10
        return res
    
    def isPrime(x):
        if x == 1:
            return False
        for i in range(2, x//2 + 1):
            if x % i == 0:
                return False
        else:
            return True
    
    n = int(stdin.readline())
    a = list(map(int, stdin.readline().split()))
    
    for x in a:
        tmp = reverse(x)
        if isPrime(tmp):
            print(tmp, end=' ')

    ▼▼点数計算


    [問題リンク]https://www.acmicpc.net/problem/2506
    from sys import stdin
    n = int(stdin.readline())
    a = list(map(int, stdin.readline().split()))
    
    sum = 0
    cnt = 0
    for x in a:
        if x == 1:
            cnt += 1
            sum += cnt
        else:
            cnt = 0
    
    print(sum)


    アルゴリズム問題を解き,二つのディックシャーサブクラスとextend()法をまとめた.

    ✏️ defaultdict


    defaultdict()はdict宣言を作成するdictクラスのサブクラスです.
    デフォルトのディックシーケンスで存在しない鍵を検索すると、鍵エラーが発生します.
    ただし、defaultdictは、存在しない鍵をクエリーする場合、エラーではなく、パラメータとしてのデフォルト値をディックシェリー値の初期値として指定できます.
    int、list、setなどを使用して初期化できるので、コードを簡単に書くことができます.

    from collections import defaultdict
    
    node = defaultdict(list)
    node[1] = ['우리집', '강아지']
    node[2] = ['두부']
    
    print(node)
    print(node[3])
    print(node)
    
    
    // 결과
    defaultdict(<class 'list'>, {1: ['우리집', '강아지'], 2: ['두부']})
    []
    defaultdict(<class 'list'>, {1: ['우리집', '강아지'], 2: ['두부'], 3: []})
    3という名前のキーはNode DickShowneryにはありませんが、エラーがエクスポートされていないことを確認でき、空のリストに初期化できます.なお、intを用いて初期化を行うとnode[3]は0に初期化される.

    ✏️ Counter


    python collectionsモジュールのCounterクラスは、リストの要素がどれだけ構成されているかを決定するために使用されます.文字列も可能です.
    サンプルコードでチェックしてみましょう.
    from collections import Counter
    
    counter = Counter('HelloWorld')
    print(counter)
    
    // 결과
    Counter({'l': 3, 'o': 2, 'H': 1, 'e': 1, 'W': 1, 'r': 1, 'd': 1})
    リストの例
    from collections import Counter
    
    test_list = ['우리집', '강아지', '두부', '두부', '개껌을', '좋아해', '개껌을', '두부']
    counter = Counter(test_list)
    print(counter.most_common(2))
    
    // 결과
    [('두부', 3), ('개껌을', 2)]
    複数の順序で出力できますが、most commonメソッドを使用して、必要な複数のリストを複数の順序で返すことができます.上記の例では、2つの要素の数が最も多いコードを抽出します.
    また、複数の演算を実行することもできます.
    減算の例
    from collections import Counter
    
    c = Counter(a=4, b=2, c=0, d=-1)
    d = Counter(a=1, b=2, c=3, d=4)
    
    c.subtract(d)
    print(c)
    
    // 결과
    Counter({'a': 3, 'b': 0, 'c': -3, 'd': -5})

    ✏️ list append() vs extend()


    [参考ブログ]https://m.blog.naver.com/wideeyed/221541104629
    Pythonリストに要素を追加する方法にはappend(x)とextend(iterable)がありますが、この2つの関数の違いを見てみましょう.
    list.append(x)は、リストの最後にx要素を保持することを表す.
    list.extend(iterable)は、一番外側のiterableのすべての項目をリストの末尾に配置します.

    append()

    a = ['우리집', '두부']
    b = ['개껌을', '좋아해']
    
    a.append(b)
    print(a)
    
    //결과
    ['우리집', '두부', ['개껌을', '좋아해']]

    extend()

    a = ['우리집', '두부']
    b = ['개껌을', '좋아해']
    
    a.extend(b)
    print(a)
    
    //결과
    ['우리집', '두부', '개껌을', '좋아해']

    文字列の場合

    a = ['우리집', '두부']
    b = '돼지야'
    
    a.extend(b)
    print(a)
    
    //결과
    ['우리집', '두부', '돼', '지', '야']

    2 Dリストの場合

    a = ['우리집', '두부']
    b = [['그래서', '돼지야']]
    
    a.extend(b)
    print(a)
    
    //결과
    ['우리집', '두부', ['그래서', '돼지야']]

    02.04金


    探索&シミュレーションに関する解題を行った

    #文文字列のチェック

    # 회문 문자열 검사
    from sys import stdin
    n = int(stdin.readline())
    
    for i in range(n):
        s = stdin.readline()
        s = s.upper() # 문자열 대문자화
        size = len(s)
    
        # for j in range(size//2):
        #     if s[j] != s[-1-j]:
        #         print("#%d NO" %(i+1))
        #         break
        # else:
        #     print("#%d YES" %(i+1))
        if s == s[::-1]:
            print("#%d YES" %(i+1))
        else:
            print("#%d No" %(i+1))
    

    数値のみ抽出

  • isdigit():本当に数字(ex 2の平方)
  • を探しました
  • isdecimal():0から9の数字
  • のみが検索されます.
    # 숫자만 추출
    from sys import stdin
    
    s = stdin.readline()
    res = 0
    for x in s:
        if x.isdecimal():
            res = res * 10 + int(x)
    print(res)
    cnt = 0
    for i in range(1, res+1):
        if res % i == 0:
            cnt += 1
    print(cnt)

    逆置きカード

    # 카드 역배치
    from sys import stdin
    
    a = list(range(21))
    for _ in range(10):
        s, e = map(int, stdin.readline())
        for i in range((e-s+1)//2):
            a[s+i], a[e-i] = a[e-i], a[s+i] # 스와프
    a.pop(0)
    for x in a:
        print(x, end=' ')

    2つのリストをマージ


    [時間複雑度比較]
    sort()=Nlognクイックソート
    使用ソート:N
    ->データが大きいほど差が大きくなります
    # 두 리스트 합치기
    from sys import stdin
    
    n = int(stdin.readline())
    a = list(map(int, stdin.readline()))
    m = int(stdin.readline())
    b = list(map(int, stdin.readline()))
    
    p1 = p2 = 0
    c = []
    while p1 < n and p2 < m:
        if a[p1] <= b[p2]:
            c.append(a[p1])
            p1 += 1
        else:
            c.append(b[p2])
            p2 += 1
    if p1 < n:
        c = c + a[p1:]
    if p2 < m:
        c = c + b[p2:]
    
    for x in c:
        print(x, end=' ')

    ▼▼▼数の和

    # 수들의 합
    from sys import stdin
    
    n, m = map(int, stdin.readline().split())
    a = list(map(int, stdin.readline()))
    lt = 0
    rt = 1
    total = a[0]
    cnt = 0
    
    while True:
        if total < m:
            if rt < n:
                total += a[rt]
                rt += 1
            else:
                break
        elif total == m:
            cnt += 1
            total -= a[lt]
            lt += 1
        else:
            total -= a[lt]
            lt += 1
    print(cnt)

    グリッドプレート最大和

    # 격자판 최대합
    from sys import stdin
    
    n = int(stdin.readline())
    a = [list(map(int, stdin.readline())) for _ in range(n)]
    
    largest = -2147000000
    for i in range(n):
        sum1 = sum2 = 0
        for j in range(n):
            sum1 += a[i][j]
            sum2 += a[j][i]
        if sum1 > largest:
            largest = sum1
        if sum2 > largest:
            largest = sum2
    
    sum1 = sum2 = 0
    for i in range(n):
        sum1 += a[i][i]
        sum2 += a[i][n-i-1]
    if sum1 > largest:
        largest = sum1
    if sum2 > largest:
        largest = sum2
    
    print(largest)