QuipperのWebエンジニア採用におけるコードテスト

こんにちは、Web エンジニアの @kechol です。

Quipper では現在、ブログを再開したり StudySapuri Meetup(Product 回Data 回)を開催したりと、採用活動に力を入れています。今日はそんな採用活動について、僕も関わっている Web エンジニアの採用プロセスの裏側を少しご紹介したいと思います。

TL;DR

  • Quipper における Web エンジニア採用プロセスにおいては、コードテストを実施しており、そのプロセスは非常に重要なものだと考えている
  • これまでアプリケーションを書いてもらうようなテストを実施していたが、候補者・採用メンバー双方の負担が大きく、改善の余地があった
  • それを受けて、より小さく、実務に近いコードでテストできるようにコードテストを改善した

Quipper における Web エンジニアの採用プロセス

Quipper における Web エンジニアの基本的な採用プロセスは、現在以下のようになっています。

  1. 書類のスクリーニング
  2. 一次面接
  3. コードテスト
  4. 二次面接
  5. VP of Engineering 面接
  6. オファー面談

Quipper では、この採用プロセスには Web エンジニアや Engineering Manager が積極的に関わっており、全てのプロセスを通して Web エンジニアが候補者の評価を行います。

各プロセスの詳細については、弊社の Quipper Web Engineer 東京オフィス採用面接ガイド もご覧ください。

コードテストというステップ

採用プロセスの中で、面接をすることは当然であっても、コードテストを行わない会社もあるかと思います。しかし Quipper において、Web エンジニアの採用メンバーは、どういう形であれコードテストのプロセスを非常に重要なステップと考えています。

Web エンジニアを含めたソフトウェアエンジニアという職は、コードを書くことで現実の問題を解決していくことが重要な職務の一つです。その職務を任せられる方かを見極めるために、その方が書いたコードを見て判断するということは理にかなっていると言えると思います。面接のような場や GitHub 等の公開リポジトリでは、実際にその方が実務で書いたコードを見られる機会は少なく、そういう意味でコードテストというステップは採用プロセスにおいて必須であると考えています。

さらに、その先の二次面接における議論を通じて、実際に一緒に働いた際にどのようなコミュニケーションになるかを確かめることができる、という点も重要です。私たちは普段チームで開発を行っており、Product Manager や Web エンジニア同士で仕様や実装について議論するということを当たり前に行っています。そうした実務上のコミュニケーションがきちんと取れる方であるかを見極めることも採用プロセスの上では大切です。

実際コードテストを実施していると、面接での印象とは全く違う結論に至ることもあり、スクリーニングプロセスとしては有効に機能していると考えています。

コードテストの是非

Quipper では従来、基本的な CRUD 操作など仕様を満たす小さな Web アプリケーションをテストを含めて書いてきてもらう、という形式のコードテストを実施していましたが、このコードテストのステップが採用候補者にとっても、採用メンバーにとっても負担を強いられるものである、というのも事実でした。

自分もこのコードテストを受けて入社した一人ではありますが、候補者にとって、転職活動をする中で、また仕事や家庭の事情がある中で、Web アプリケーションを一つ作るということが負担であることは想像にかたくありません。

また、小さな Web アプリケーションと言っても、人によって書きようは様々です。特に Quipper では以下のような問題がありました。

  • 合否の判断をしている部分とは別の部分に時間をかけてしまえること
    • 仕様を満たせば技術を自由に選定し、こだわろうと思えばいくらでもこだわれてしまうため
    • 候補者にとってはより多くの技術を見せたほうが合格確率が上がるだろう、というインセンティブが働くため
  • 候補者によって利用しているフレームワーク、ライブラリが大きく違う場合があること
    • Quipper が実際に使用する技術を推奨してはいるものの、候補者自身の判断で自由に技術要素を選べてしまうため

最終的に候補者の合否を決定しなければいけないという場面では、こういったケースはレビューする側での合否の判断が難しく、レビューに時間がかかる、合否結果に揺れがあり得るという懸念がありました。

こうしたコードテストの問題点について、採用メンバーの間でも議論となり、コードテストの見直しをすることとなりました。

コードテストの見直し

コードテストを見直すにあたっては、なるべく候補者の負担にならない形で実施でき、かつ、テストに合格した候補者は Quipper で活躍できることが保証できる、ということが理想的だと考えています。

まず候補者の負担を減らすにあたっては、Web アプリケーションを丸ごと一つ作っていただくのではなく、その中の要素技術やコアロジックに絞って出題するような形に変更することで、候補者に何を回答として求めているのか明確になるようにしていきたいと考えました。

また、テストに合格した時点で Quipper で活躍できることが保証できるようにするためには、より実務的なコードをテストとして出題する必要があると考えました。fizzbuzz のような基本的なプログラミング能力を問う問題だけでは不十分であり、Quipper で利用している Web アプリケーションフレームワークを使ったロジックが書けるかどうかを確認したいのです。

実際のコードテストのイメージ

コードを見せたほうがイメージが湧くだろう思うので、現在のコードテストと似たテンプレートをお見せします。上述の通り、新しいコードテストにおいては、候補者に回答を求める部分が明確で、かつ実務のコードに近いようなものになることを理想としています。

そうした理想を叶えるために、以下のようなテストを考えています。

require "bundler/inline"

gemfile do
  source "https://rubygems.org"
  gem "activerecord"
  gem "sqlite3"
  gem "minitest"
end


require "active_record"
require "minitest/autorun"

class Question < ActiveRecord::Base
  validates :content, presence: true
  validates :answer, numericality: { only_integer: true, greater_than: 0 }

  def self.with_prime_answers_under_100
    # TODO: Implement me!
  end
end


class QuestionTest < Minitest::Test
  def setup
    ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
    ActiveRecord::Schema.define do
      create_table :questions do |t|
        t.string  :content, null: false
        t.integer :answer,  null: false
      end
    end

    101.downto(1) do |i|
      Question.create!(content: "Question #{i}", answer: i)
    end
  end

  def test_with_prime_answers_under_100
    questions = Question.with_prime_answers_under_100
    primes = Set[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
    assert_equal primes, questions.map(&:answer).to_set
  end
end

このテストは 100 以下の素数を回答にもつ Question を DB から取得し列挙するメソッド Question.with_prime_answers_under_100 を実装してもらうテストです。

シンプルに解くと以下のような感じになると思います。

@@ -8,6 +8,7 @@ gemfile do
 end


+require "prime"
 require "active_record"
 require "minitest/autorun"

@@ -16,7 +17,7 @@ class Question < ActiveRecord::Base
   validates :answer, numericality: { only_integer: true, greater_than: 0 }

   def self.with_prime_answers_under_100
-    # TODO: Implement me!
+    where(answer: Prime.each(100).to_a)
   end
 end

このテストで使われている ActiveRecord は普段 Rails を書いている Web エンジニアにとって馴染みのあるものであり、単に 100 以下の素数を列挙できるかというようなプログラミング能力の問題に加えて、DB へのアクセス数を想定できるか、Rails の Model としてどのようにコードを構成するかといった観点が出てきます。

また、この形式には他にも以下のようなメリットがあります。

  • 見たい観点を明確にしてより小さな構成にまとめることで、候補者がロジックを書き始めるまでの迷いがなくなる
  • 実行できるテストを一緒に提供することで、期待する仕様を満たしているかどうかの判断が容易になる

実際の合否判断においては、テストが通っていることを前提として、書いていただいたコードが僕らから見て理にかなっているかを加味して判断しています。

この例では Model を扱うテストでしたが、他にもこうした小さなコードで収まるようなものをいくつかの観点に分けて出題しています。実際の問題はもう少し難しいものになるかもしれませんね ;)


というわけで、Quipper における Web エンジニアのコードテストについてご紹介しました。まだまだ改善の余地のあるものではありますが、コードテストを含め、引き続き Web エンジニアが採用プロセスを主体的に改善していくことで、お互いにとって不幸なミスマッチを防ぎ、より良いエンジニア組織づくりができると信じています。

良いコードテストを Quipper で一緒に考えてみたい、もしくはどんな出題がされるのか気になるのでコードテストを受けてみたい、という方はぜひご応募ください。