• トップ
  • ブログ一覧
  • バックエンドのテストコードの書き方をどう学んだか振り返ってみる
  • バックエンドのテストコードの書き方をどう学んだか振り返ってみる

    こま(エンジニア)こま(エンジニア)
    2026.06.10

    IT技術

    概要

    バックエンドのテストコードの書き方を、行き当たりばったりで学んできました。実装コードに比べて体系的な情報が少なく、「どう書けば実務に耐えるテストになるのか」を独学でつかむまでにずいぶん遠回りをしたと感じています。

    本記事では、4年ぐらいテストコードについて試行錯誤しながら何をどう学んできたか振り返ってみます。

    この記事のターゲット

    主な読者は次のような方を想定しています。

    • これからテストコードを書き始めたいバックエンドエンジニア
    • なんとなくテストコードを書いてはいるが、「よいテストコード」の判断軸に自信が持てない方

    対象はWebアプリケーションに絞っていますが、考え方自体はほかのドメインでも応用できるはずです。

    記事の構成

    テストコードを書く最初の一歩から、プロジェクト全体でテストコードを運用できるようになるまでにやったこと・悩んだことなどを3つのステップに整理しました。

    各ステップでは、参考になった書籍・リポジトリ・ドキュメントを添えています。気になったものから拾い読みしていただける構成です。

    また、今回の記事はペアで執筆しているので、ペアの矢野さんにも随所にコメントを添えてもらっています。
    矢野さんはテストコードについてどのような経験をしてきたのか、簡単に載せておきます。

    矢野プロフィール-テストコードについて

    テストコードの経験ライトコードに入ってからなので3年くらいで、現在は物件データのインポートや名寄せ処理のテストコードをよく書いてます。
    開発言語はRubyでフレームワークはrspecを使用しています。データの量や種類が多いので、テストコードの書きがいがあります。

    前職では、テストコードがないプロジェクトに1~2年ほど在籍していて、それによる予期しないバグで、サービス残業を強いられることがよくあったので、テストコードの恩恵はすごく感じている立場です笑

    余談:AI時代にテストコードの書き方を学ぶ意義

    AIによるコーディング支援が当たり前になり、TDDとAIを組み合わせた開発スタイルもよく耳にするようになりました。テストコードもAIに書いてもらえる時代です。
    しかし、生成されたテストコードがプロジェクトに本当に役立つのか、判断するには人間側の知識や経験が必要です。

    つまり、何がいいテストコードなのか見極められるようになることは、今の時代においても重要だと考えています。

    そして何より、テストコードを書くこと自体が単純に楽しいので、趣味として手を動かして理解を深めていくのもよいものです。

    「生成されたテストコードがプロジェクトに本当に役立つのか、判断するには人間側の知識や経験が必要です。」

    矢野コメント:

    最近、AIエージェント等でテストコードを生成してもらったとき、「テストは通るけど、これって本当に意味のある検証をしてるのか?」と感じることが何度かありました。

    テストが増えると一見安心感があるのですが、カバレッジを埋めるためだけのテストは、むしろ変更のコストを上げるだけになりかねないんですよね。
    AIが書いたテストに「GOを出せる目」を養うことが、これからのエンジニアに求められるスキルだと改めて思います。


    ステップ1:はじめてのテスティングフレームワーク

    最初の一歩は、テスティングフレームワークの導入から始まりました。言語やツールは自分の好きなものを選ぶのがよさそうですが、これから始めるなら pytest がやりやすいと思います。

    最近は uv で環境構築も楽になったので、サクッとテストコードを書くための準備が整います。

    このステップで学びたいこと

    まずはテスティングフレームワークの使い方を押さえれば、最初のハードルは越えられます。あわせて、テストコードを書くときの基本構文として Given-When-Then を常に意識しておくと、読み書きするときに迷子になりにくくなります。

    参考リポジトリ

    テスティングフレームワークは自分自身をテストするテストコードを書いている場合が多く、参考にするのにおすすめです。たとえばpytestのリポジトリのテストコードを覗くと、テストコードの基本的な書き方とpytestの挙動の両方を理解できます(参考)。

    ボリュームは多いので、気になったところを流し読みするだけでも十分力はつきます。ここでは特に面白いと感じた部分を抜粋します。

    出典: GitHub - pytest-dev/pytest: https://github.com/pytest-dev/pytest

    1# https://github.com/pytest-dev/pytest/blob/main/testing/logging/test_fixture.py
    2# testing/logging/test_fixture.py
    3
    4logger = logging.getLogger(__name__)
    5sublogger = logging.getLogger(__name__ + ".baz")
    6
    7# fixture の使い方の雰囲気をつかむのに Good
    8@pytest.fixture(autouse=True)
    9def cleanup_disabled_logging() -> Iterator[None]:
    10    """Simple fixture that ensures that a test doesn't disable logging.
    11
    12    This is necessary because ``logging.disable()`` is global, so a test disabling logging
    13    and not cleaning up after will break every test that runs after it.
    14
    15    This behavior was moved to a fixture so that logging will be un-disabled even if the test fails an assertion.
    16    """
    17    yield
    18    logging.disable(logging.NOTSET)
    19
    20# 特定のログレベルのログのみが記録されたかを検証するテストコード
    21# caplog の使い方を知れるだけでなく、Given-When-Then の構造をつかむのにもよいサンプル
    22# 一例としてコメントでGiven-When-Thenを添える
    23def test_change_level(caplog: pytest.LogCaptureFixture) -> None:
    24    # Given
    25    caplog.set_level(logging.INFO)
    26
    27    # When
    28    logger.debug("handler DEBUG level")
    29    logger.info("handler INFO level")
    30    caplog.set_level(logging.CRITICAL, logger=sublogger.name)
    31    sublogger.warning("logger WARNING level")
    32    sublogger.critical("logger CRITICAL level")
    33
    34    # THEN
    35    assert "DEBUG" not in caplog.text
    36    assert "INFO" in caplog.text
    37    assert "WARNING" not in caplog.text
    38    assert "CRITICAL" in caplog.text

    膨大なテストコードの中から参考になりそうな箇所を探すときは、AIの力を借りるとぐっと捗ります。ログ・一時ディレクトリ・モックなど、自分が使いたい機能を起点に探してもらうイメージです。

    たとえば以下のようなプロンプトを渡すことで、testing/test_tmpdir.py の存在を知ることができます。

    1ファイルの読み書きのテストコードを書きたいです。
    2pytest ではどのように書くのがよいか理解するため、
    3以下の pytest のリポジトリから参考になるテストファイルを教えてください。
    4https://github.com/pytest-dev/pytest/tree/main/testing

    pytestは十分にメンテナンスされているため、「テストコードでこれをやりたい」と思ったときに、ドキュメントとテストコードの両方からイメージを深められます。

    読んでよかった書籍

    『テスト駆動Python』は、テストコードを書いてみたいが何から始めればよいかわからないときに、最初に手に取るのによかったです。通読しなくても、序盤の章をいくつか眺めるだけで入門フェーズは乗り切れます。

    『はじめて学ぶソフトウェアのテスト技法』は、テストコードの書き方そのものは扱われていませんが、「何をテストとして書くべきか」を考える力を身につけるのに役立ちました。境界値テスト・デシジョンテーブルといった、単体テスト以降のフェーズでも助けられる知識が得られます。


    ステップ2:テストコードをひたすら読み書きする

    ステップ1でテストコードへの入門は果たせました。簡単なロジックであれば自信を持って書けそうな感覚は得られますが、業務で扱うコードはより複雑で規模も大きいです

    業務レベルのロジックを対象にテストコードを書けるようになるには、次に何をすればよいかを整理します。

    このステップで学びたいこと

    実装コードの書き方をたくさん読み書きして身につけたのと同じく、テストコードも読み書きを繰り返すことが重要です。テストケースの読みやすさ・書きやすさを経験として重ねることで、テストケースのよしあしを見る目を養うことを目指します。

    参考リポジトリ

    ステップ2の段階ではとにかく量を読みたいので、参考になりそうなものを抜粋します。ここではPythonのWebアプリケーションフレームワークDjangoに関連するリポジトリを取り上げます。

    他の言語やフレームワークで探したい場合は、GitHubのトピックページから好きな言語・フレームワークでスターの多いリポジトリを漁ってみると、めぼしいものが見つかるはずです(参考)。

    django-environDjango REST framework は、Djangoに関係しつつpytestでテストコードを書いているため、書き方に悩んだときに参照するのにちょうどよいです。

    一つ覗いてみましょう。

    出典: GitHub - encode/django-rest-framework: https://github.com/encode/django-rest-framework

    1# https://github.com/encode/django-rest-framework/blob/main/tests/test_validators.py
    2# tests/test_validators.py
    3
    4class TestUniquenessValidation(TestCase):
    5    def setUp(self):
    6        self.instance = UniquenessModel.objects.create(username='existing')
    7
    8    # テストケースの命名と構造に注目する
    9    # テストしたい対象の状態で命名し、
    10    # 期待値 → 実際に得られたオブジェクトを比較してアサーションとする構造を読み取りたい
    11    def test_is_not_unique(self):
    12        # Given
    13        data = {'username': 'existing'}
    14        # When
    15        serializer = UniquenessSerializer(data=data)
    16        # Then
    17        assert not serializer.is_valid()
    18        assert serializer.errors == {'username': ['uniqueness model with this username already exists.']}
    19
    20    def test_relation_is_not_unique(self):
    21        RelatedModel.objects.create(user=self.instance)
    22        data = {'user': self.instance.pk}
    23        serializer = RelatedModelUserSerializer(data=data)
    24        assert not serializer.is_valid()
    25        assert serializer.errors == {'user': ['related model with this user already exists.']}
    26
    27    def test_is_unique(self):
    28        data = {'username': 'other'}
    29        serializer = UniquenessSerializer(data=data)
    30        assert serializer.is_valid()
    31        assert serializer.validated_data == {'username': 'other'}

    この例では、シリアライザオブジェクト(出力として得られたオブジェクト)に __eq__() を定義して等価比較すれば、より厳密な検証も可能です。とはいえ、それではテストコード側の期待値定義が長くなり、実装コード側にも比較用のメソッドが生えて複雑になってしまいます。

    「どこに・何を・どこまで書けば読み書きしやすいテストコードになるのか」たくさん読み書きしながら身につけたいです。

    失敗経験:テストコードにロジックを書きすぎた期

    趣味コードで実験的にテストコードを書いていた頃は、実装コードと同じ考えでテストコードを書き殴っていました。
    具体的には、ループ・共通化をふんだんに取り入れることで、テストコードにロジックをたくさん持たせていました。
    書き終わってすぐは満足していましたが、少し日を空けて読み返すと個々のテストケースで何を検証したいのか読み解きづらくなっていました。

    サンプルとして、過去に趣味でつくったマークダウンパーサーのサービス層に相当するところのテストコードを載せます。
    あくまでアンチパターンなので、ぱっと見で何を検証しているか見えづらい。ということだけ掴めればOKです。

    1class TestTocNodeTreeGenerator:
    2    """ ヘッダBlockから目次構造のツリーをつくれるか検証 """
    3
    4    # ヘッダから対応する目次構造のツリーをつくれるか
    5    @pytest.mark.parametrize(
    6        ('header_text_list', 'expected_list'),
    7        [
    8            (
    9                ['# 概要'],
    10                [TocNode(depth=1, text='概要', children=[])]
    11            ),
    12            (
    13                ['# 概要', '## ゴール'],
    14                [TocNode(depth=1, text='概要', children=[
    15                    TocNode(depth=2, text='ゴール', children=[])])
    16                 ]
    17            ),
    18            (
    19                ['# 概要', '## 用語整理', '### Pythonとは', '#### 補足: Pythonの由来', '### たのしいPython'],
    20                [TocNode(depth=1, text='概要', children=[
    21                    TocNode(depth=2, text='用語整理', children=[
    22                        TocNode(depth=3, text='Pythonとは', children=[
    23                            TocNode(depth=4, text='補足: Pythonの由来', children=[])
    24                        ])
    25                        , TocNode(depth=3, text='たのしいPython', children=[])
    26                    ])
    27                ])]
    28            ),
    29            (
    30                ['# 目次の`テスト`', '## [link](url)'],
    31                [TocNode(depth=1, text='目次のテスト', children=[
    32                    TocNode(depth=2, text='link', children=[])
    33                ])]
    34            )
    35        ],
    36        ids=['single element', 'single child', 'multiple child', 'contains inline element']
    37    )
    38    def test_generate_single_tree(self, header_text_list: list[str], expected_list: list[TocNode]):
    39        # GIVEN
    40        sut = TocNodeTreeGenerator()
    41        block_list = MarkdownParser().parse(header_text_list).content
    42        header_list = [block for block in block_list if isinstance(block, HeadingBlock)]
    43
    44        # WHEN
    45        actual_list = sut.generate(header_list)
    46        # THEN
    47        for actual, expected in zip(actual_list, expected_list):
    48            assert actual == expected

    テストコードが読みづらいと、メンテナンスするのも大変になりそうです。
    この問題を解消するため、テストコードはドキュメントだと捉え、テストクラス名・テストケース名からまずはやりたいことを大まかに把握できるようになることを目指しました。

    そして、振る舞いに着目できるようテストコードもシンプルにすることを目指していったのですが、その辺りはステップ3に関わる話なので、次節以降で触れます。

    矢野コメント:

    私も全く同じ失敗をしたことがあります。。。
    「DRYにしないと」という気持ちが、テストコードでは裏目に出ることがあるんですよね。
    テストを共通化しすぎると、1つのテストが落ちたときに「何を壊したのか」が分からなくなる。
    「テストコードを書くこと」が目的になっていて、テストコードを「何のために書いているのか」を忘れてしまっていることがあるんですよね。。。
    だって楽しいんだもん!笑


    ステップ3:よいテストコードとは何かを考える

    前のステップではテストコードを読み書きすることで、業務レベルのテストコードを書けるようになることを目標としました。ここまでがんばれば、既存システムを改修するときに、足りていない箇所へテストを追加できるレベルには達します。

    ただし、Webアプリケーションの実装コードはモデル・ビュー・サービス・バッチなど、さまざまなレイヤーから構成されています。そして、実装コードは要件に応じて複雑にかつ高速に変化していきます。

    つまり、「一つの処理を検証するテストコードを書ける」だけでは、耐えず変化する実装コードをテストし続けるという目的を満たすには、不十分なのです。

    このステップで学びたいこと

    どのレイヤーを対象に・どんなテストコードを書けば、変更しやすくかつ壊れにくいテストコードが書けるのか。テストコード全体の構造を考えられるようになることを目指します。

    これまでは「目の前のテストコード1つ」を改善したり、見よう見まねで書いたりすることで書き方を身につけてきました。しかしここからは、テストコード全体の設計を考える必要があります。抽象度の高い課題なので、まずは考えを深めるのにとてもよかった書籍を紹介します。

    読んでよかった書籍

    『単体テストの考え方/使い方』が、私のテスト観に大きな影響を与えてくれました。値段も文量も中々のもので読み終わるまでにけっこうな時間がかかりましたが、テストコードのよしあしを考える判断軸はこの本で整理できたと感じています。

    テストコードはシステムの振る舞いを検証し、退行を検出するのが目的である。という考え方をさまざまな視点から見つめることで、いいテストコードを書くために何を考えればよいか見出せるようになることを目指します。

    参考リポジトリ

    Django管理画面のテストコード

    Django管理画面のテストコードは、管理画面という具体的なシステムの振る舞いをどう検証しているかという点で、大いに参考にできます。特に tests.py は膨大な量のテストコードが書かれていますが、幅広い振る舞いを対象としているので、ざっと眺めるだけでも学びがあります。

    いくつかテストコードを見てみましょう。

    出典: GitHub - django/django: https://github.com/django/django

    1# https://github.com/django/django/blob/main/tests/admin_views/tests.py
    2# tests/admin_views/tests.py
    3
    4@override_settings(
    5    MAILERS={"default": {"BACKEND": "django.core.mail.backends.locmem.EmailBackend"}}
    6)
    7class AdminViewBasicTest(AdminViewBasicTestCase):
    8    # 振る舞いのみをテストしているので、HTTP リクエストを送り、ステータスコードを確認するのみ
    9    def test_trailing_slash_required(self):
    10        """
    11        If you leave off the trailing slash, app should redirect and add it.
    12        """
    13        add_url = reverse("admin:admin_views_article_add")
    14        response = self.client.get(add_url[:-1])
    15        self.assertRedirects(response, add_url, status_code=301)
    16
    17    def test_basic_add_GET(self):
    18        """
    19        A smoke test to ensure GET on the add_view works.
    20        """
    21        response = self.client.get(reverse("admin:admin_views_section_add"))
    22        self.assertIsInstance(response, TemplateResponse)
    23        self.assertEqual(response.status_code, 200)

    これだけでは振る舞いベースのテストの輪郭が見えづらいので、もう少し具体的なものを探してみます。管理画面の保存ボタンからデータベースにデータを登録する処理のテストコードを見てみましょう。

    出典: GitHub - django/django: https://github.com/django/django

    1@override_settings(ROOT_URLCONF="admin_views.urls")
    2class SaveAsTests(TestCase):
    3    @classmethod
    4    def setUpTestData(cls):
    5        cls.superuser = User.objects.create_superuser(
    6            username="super", password="secret", email="super@example.com"
    7        )
    8        cls.per1 = Person.objects.create(name="John Mauchly", gender=1, alive=True)
    9
    10    def setUp(self):
    11        self.client.force_login(self.superuser)
    12
    13    # 複製で保存したいとき、元データを残して新しいデータを登録するという振る舞いを検証
    14    def test_save_as_duplication(self):
    15        """'save as' creates a new person"""
    16        post_data = {"_saveasnew": "", "name": "John M", "gender": 1, "age": 42}
    17        response = self.client.post(
    18            reverse("admin:admin_views_person_change", args=(self.per1.pk,)), post_data
    19        )
    20        self.assertEqual(len(Person.objects.filter(name="John M")), 1)
    21        self.assertEqual(len(Person.objects.filter(id=self.per1.pk)), 1)
    22        new_person = Person.objects.latest("id")
    23        self.assertRedirects(
    24            response, reverse("admin:admin_views_person_change", args=(new_person.pk,))
    25        )
    26
    27    # 保存後の画面遷移という振る舞いを検証
    28    def test_save_as_continue_false(self):
    29        """
    30        Saving a new object using "Save as new" redirects to the changelist
    31        instead of the change view when ModelAdmin.save_as_continue=False.
    32        """
    33        post_data = {"_saveasnew": "", "name": "John M", "gender": 1, "age": 42}
    34        url = reverse(
    35            "admin:admin_views_person_change",
    36            args=(self.per1.pk,),
    37            current_app=site2.name,
    38        )
    39        response = self.client.post(url, post_data)
    40        self.assertEqual(len(Person.objects.filter(name="John M")), 1)
    41        self.assertEqual(len(Person.objects.filter(id=self.per1.pk)), 1)
    42        self.assertRedirects(
    43            response,
    44            reverse("admin:admin_views_person_changelist", current_app=site2.name),
    45        )
    46
    47    # バリデーションエラーが画面に表示されるかという振る舞いを検証
    48    def test_save_as_new_with_validation_errors(self):
    49        """
    50        When you click "Save as new" and have a validation error,
    51        you only see the "Save as new" button and not the other save buttons,
    52        and that only the "Save as" button is visible.
    53        """
    54        response = self.client.post(
    55            reverse("admin:admin_views_person_change", args=(self.per1.pk,)),
    56            {
    57                "_saveasnew": "",
    58                "gender": "invalid",
    59                "_addanother": "fail",
    60            },
    61        )
    62        self.assertContains(response, "Please correct the errors below.")
    63        self.assertFalse(response.context["show_save_and_add_another"])
    64        self.assertFalse(response.context["show_save_and_continue"])
    65        self.assertTrue(response.context["show_save_as_new"])

    サービス層やユースケース層を直接呼び出してテストするのではなく、HTTPリクエストを送って、データベースの状態や画面の表示レベルまで検証している点が特徴です。「何を振る舞いとし、どこまでテストを書くべきか」は悩ましいところですが、Django管理画面のテストコードは参考にできるところが多そうです。

    django-shopのテストコード

    django-shop は、Django製のECサイト構築用フレームワークです。長らくメンテナンスはされていないようですが、実際のサイトの振る舞いをどのように検証しているかという点で参考にできるところが多いです。

    出典: GitHub - awesto/django-shop: https://github.com/awesto/django-shop

    1# https://github.com/awesto/django-shop/blob/master/tests/test_checkout.py
    2# tests/test_checkout.py
    3
    4# HTTP リクエストを送り、結果としてデータベースがどう変動したかをもって振る舞いを観測するテスト
    5@pytest.mark.django_db
    6def test_add_shipping_address(registered_customer, api_rf, empty_cart, address_data):
    7    data = dict(shipping_address=address_data, active_priority='add')
    8    request = api_rf.put('/shop/api/checkout/upload', data, format='json')
    9    request.customer = registered_customer
    10    request.user = registered_customer.user
    11    assert registered_customer.shippingaddress_set.count() == 0
    12    assert registered_customer.billingaddress_set.count() == 0
    13
    14    # データ更新
    15    response = CheckoutViewSet.as_view({'put': 'upload'})(request)
    16    assert response.status_code == 200
    17    assert response.data['shipping_address_form']['name'] == address_data['name']
    18    label = "1. John Doe – 31 Orwell Road – L41RG Liverpool – United Kingdom"
    19    assert response.data['shipping_address_form']['siblings_summary'][0]['label'] == label
    20    registered_customer.refresh_from_db()
    21    assert registered_customer.billingaddress_set.count() == 0
    22    shipping_address = registered_customer.shippingaddress_set.first()
    23
    24    # アサーション
    25    assert shipping_address
    26    assert shipping_address.name == address_data['name']
    27    assert shipping_address.address1 == address_data['address1']
    28    assert shipping_address.zip_code == address_data['zip_code']
    29    assert shipping_address.city == address_data['city']
    30    assert shipping_address.country == address_data['country']

    fixtureをふんだんに使い、テストコード自体も多くのステップで構成されています。Django管理画面よりも準備フェーズが増えていますが、やりたいことの本質は変わりません。

    HTTPリクエストを送り、レスポンスやデータベースの状態から、あるべき振る舞いが保たれているかを検証する。これを実現するためにリクエストファクトリやfixtureを用意するなど多少複雑になっても、根本の考え方はぶれません。

    失敗経験:サービス層にテストを書きすぎた期

    シンプルな入力を受け取り、出力のオブジェクトからテストコードを書くよう設計すると、スムーズにテストコードが書けて楽しいです。
    CIのテストも高速でパスすることで、自信をもって開発できるようになっていました。
    ただ、システムの振る舞いにフォーカスせず、入出力をテスト可能な形に収めることに集中してしまっていたので、結合テストぐらいで問題が出てきました。
    具体的には、バグが見つかって修正するとメソッドの入力が微妙に変わってテストが通らなくなる、などテストコードが壊れやすくなってしまっていました。

    『単体テストの考え方/使い方』でも言及されていた通り、テストコードは振る舞いを検証し、退行を検出するのが目的。ということを意識することで、どのレイヤーで・どんな理由で・どんなテストコードを書くべきか考えられるようにしたいです。

    振り返り-よいテストコードとは何か

    ここまで、参考になる書籍やリポジトリ・そして過去の失敗談を見てきました。
    少し長くなってしまったので、理解の復習として「よいテストコード」とは何か改めて言葉でまとめてみようと思います。

    よいテストコードは、リファクタリング・回帰テストに役立つと共に、それ自体が機能の持つ振る舞いを表現したドキュメントとなっていること。だと考えています。

    読みやすく・壊れにくい。加えて、テストコードを読んでいけば機能がどんな振る舞いをしていくのか掴むことができる。
    これを満たすことができれば、変化の速いソフトウェア開発の時代でも堅牢なシステムをつくるのに役立つ「いいテストコード」になってくれます。

    矢野コメント:

    「リファクタリング耐性があり、かつ振る舞いを表現したドキュメントである」というまとめ、すっきりしていて良きですね。

    これに関連して、私が意識しているのは「テストコードを書く前に、テストケース名だけ先に書く」という習慣です。it 存在しないユーザーでログインするとエラーが返る do のような名前を先に並べておくと、自然と振る舞いベースの設計になると思ってます。
    AIエージェントと開発する際も、先に振る舞いの名前だけのリスト書いてもらって、私がレビューすることもあります。この段階のレビューであれば負荷が少ないですし、よりドキュメントとして読みやすく感じています。


    まとめ

    まだまだ手探りでテストコードを書いている状態ではありますが、これまでの試行錯誤を3つのステップで振り返りました。整理すると、次のような学びがありました。

    • ステップ1:テスティングフレームワークを1つ決めて手を動かし、Given-When-Thenを基本構文として身体に染み込ませる
    • ステップ2:テストコードはドキュメントだと捉え、共通化よりも「単体で読めること」を優先する。読み書きの絶対量を増やす
    • ステップ3:「振る舞いの検証」を軸に据え、どのレイヤーでテストを書くかを目的から逆算する

    寄り道しながら学んできた過程の一部でも、これからテストコードと向き合うみなさんの参考になればうれしいです。

    矢野コメント:

    記事を読んで、自分のテストコードとの向き合い方を改めて振り返る機会になりました。
    3つのステップに整理されているのがわかりやすくて、「自分は今どのステップにいるか」を確認できる地図のような記事だと思います。

    私自身はまだステップ2と3の間をうろうろしている感覚があるので、紹介されていた『単体テストの考え方/使い方』を手に取るモチベーションが改めて湧いてきました。

    テストコードは書けるようになると確かに楽しいですし、いいテストコードが装備されていると「安心して開発できる」と実感することがよくあります。
    そして、テストコードは守りの技術だと強く思います。

    AI時代は、開発スピード等、攻めの話が多く取り沙汰されますが、自分の関わるプロジェクトを守るためにも、テストの知識や技術はこれからも必須だなと改めて考えさせられました。

    ライトコードでは、エンジニアを積極採用中!

    ライトコードでは、エンジニアを積極採用しています!カジュアル面談等もございますので、くわしくは採用情報をご確認ください。

    採用情報へ

    おすすめ記事

    エンジニア大募集中!

    ライトコードでは、エンジニアを積極採用中です。

    特に、WEBエンジニアとモバイルエンジニアは是非ご応募お待ちしております!

    また、フリーランスエンジニア様も大募集中です。

    background