เมื่อคุณเริ่มเขียน unit tests เป็นครั้งแรก มันอาจจะรู้สึกไม่เป็นธรรมชาติ สิ่งหนึ่งที่คนมักเจอก็คือความรู้สึกว่า tests ของพวกเขามาขวางทาง เวลาเดินดูโปรเจกต์ไปเรื่อยๆ บางทีก็ลืมไปว่ากำลังดู test code หรือ production code อยู่ การที่คุณเริ่มมี test code เยอะขึ้นก็ไม่ได้ช่วยอะไรเลย ถ้าคุณไม่เริ่มกำหนด conventions บางอย่างขึ้นมา สุดท้ายคุณอาจจะจมอยู่กับมัน

Class Naming Conventions (หลักเกณฑ์การตั้งชื่อคลาส)

สิ่งแรกๆ ที่ควรกำหนดคือ class naming convention โดยทั่วไปแล้วคุณจะมี unit test class อย่างน้อยหนึ่งคลาสสำหรับแต่ละคลาสที่คุณทำงานด้วย ดังนั้นการตั้งชื่อ unit test class ให้เป็นรูปแบบที่แตกต่างจากชื่อคลาสเดิมก็เป็นเรื่องที่สมเหตุสมผล มี conventions อยู่สองสามแบบที่นิยมใช้กัน แบบที่พบบ่อยที่สุดคือการใช้คำว่า Test เป็น prefix หรือ suffix ของชื่อคลาส เช่น ถ้าเรามีคลาสชื่อ DBEngine, เราก็สามารถตั้งชื่อ test class ว่า TestDBEngine หรือ DBEngineTest. จะแตกต่างกันไหม? ก็ไม่จริงๆ แล้วผมชอบใช้ Test เป็น suffix มากกว่า ถ้าคุณมี IDE ที่เรียงคลาสตามตัวอักษร แต่ละคลาสก็จะอยู่ติดกับ test class ของมัน ทำให้การนำทางระหว่างคลาสพวกนี้ง่ายขึ้น

แล้วมีคลาสอื่นๆ อะไรอีกที่เกิดขึ้นในการทดสอบ? บ่อยครั้งที่การ fake classes สำหรับ collaborators บางตัวของคลาสใน package หรือ directory หนึ่งๆ ก็มีประโยชน์ โดยปกติแล้ว convention ที่ผมใช้คือการใช้ prefix Fake ซึ่งจะทำให้คลาสพวกนี้รวมกลุ่มกันตามตัวอักษรใน browser แต่อยู่ห่างจากคลาสหลักใน package พอสมควร มันสะดวกเพราะว่า fake classes มักเป็น subclass ของคลาสใน directory อื่นๆ

อีกคลาสประเภทหนึ่งที่มักใช้ในการทดสอบคือ testing subclass ซึ่งเป็นคลาสที่คุณเขียนขึ้นมาเพราะต้องการทดสอบคลาสใดคลาสหนึ่ง แต่มี dependencies บางอย่างที่คุณอยากแยกออกไป เป็น subclass ที่คุณเขียนเมื่อใช้เทคนิค Subclass and Override Method (401) convention การตั้งชื่อที่ผมใช้สำหรับ testing subclasses คือชื่อคลาสเดิมโดยมีคำว่า Testing นำหน้า ถ้าคลาสใน package หรือ directory ถูกเรียงตามตัวอักษร testing subclasses ทั้งหมดก็จะรวมกลุ่มกัน

ต่อไปนี้คือตัวอย่างรายการใน directory ของ package ทางบัญชีขนาดเล็ก:

• CheckingAccount

• CheckingAccountTest

• FakeAccountOwner

• FakeTransaction

• SavingsAccount

• SavingsAccountTest

• TestingCheckingAccount

• TestingSavingsAccount

สังเกตว่าแต่ละ production class จะอยู่ติดกับ test class ของมัน fakes จะรวมกลุ่มกัน และ testing subclasses ก็รวมกลุ่มกัน

ผมไม่ได้ยึดติดกับรูปแบบนี้แบบตายตัว มันใช้ได้ในหลายกรณี แต่ก็มีรูปแบบอื่นๆ และเหตุผลอีกมากมายที่จะปรับเปลี่ยนมัน สิ่งสำคัญที่ต้องจำไว้คือ ergonomics เป็นเรื่องสำคัญ ต้องคำนึงถึงว่าการนำทางกลับไปกลับมาระหว่างคลาสของคุณกับ tests ของคุณจะสะดวกแค่ไหน

Test Location (ตำแหน่งที่วาง Test)

จนถึงตอนนี้ในบทนี้ ผมได้ตั้งสมมติฐานว่าคุณจะวาง testing code และ production code ไว้ใน directories เดียวกัน โดยทั่วไปแล้วนี่เป็นวิธีที่ง่ายที่สุดในการจัดโครงสร้างโปรเจกต์ แต่ก็มีบางสิ่งที่คุณต้องพิจารณาเมื่อจะตัดสินใจว่าจะทำแบบนี้หรือไม่

สิ่งหลักที่ต้องพิจารณาคือว่ามีข้อจำกัดด้านขนาดของการ deploy แอปพลิเคชันของคุณหรือไม่ แอปพลิเคชันที่รันบนเซิร์ฟเวอร์ที่คุณควบคุมอาจไม่มีข้อจำกัดมากนัก ถ้าคุณทนกับการใช้พื้นที่ในการ deploy เพิ่มขึ้นเป็นสองเท่า (binaries ของ production code และ tests) ได้ ก็ง่ายที่จะเก็บโค้ดและ tests ไว้ใน directories เดียวกันและ deploy binaries ทั้งหมด

ในทางกลับกัน ถ้าซอฟต์แวร์เป็นผลิตภัณฑ์เชิงพาณิชย์และรันบนเครื่องของคนอื่น ขนาดของ deployment อาจเป็นปัญหาได้ คุณอาจพยายามแยก testing code ทั้งหมดออกจาก production source แต่ก็ต้องพิจารณาว่าสิ่งนี้ส่งผลต่อการนำทางโค้ดของคุณหรือไม่

บางครั้งมันก็ไม่แตกต่างอะไร ดังตัวอย่างนี้ ใน Java package สามารถครอบคลุมสอง directories ที่แตกต่างกัน:

source
     com
         orderprocessing
              dailyorders

test
     com
         orderprocessing
              dailyorders

เราสามารถใส่ production classes ใน dailyorders directory ภายใต้ source, และ test classes ใน dailyorders directory ภายใต้ test, และคลาสเหล่านี้จะถูกมองว่าอยู่ใน package เดียวกัน บาง IDE สามารถแสดงคลาสจากสอง directories นั้นในมุมมองเดียวกันได้ ทำให้คุณไม่ต้องสนใจว่าพวกมันอยู่ที่ไหนจริงๆ

ในภาษาอื่นๆ และสภาพแวดล้อมอื่นๆ หลายภาษา ตำแหน่งที่วางนั้นมีความแตกต่าง ถ้าคุณต้องนำทางขึ้นลงตามโครงสร้าง directory เพื่อกลับไปกลับมาระหว่างโค้ดของคุณกับ tests ของมัน มันก็เหมือนกับการเสียภาษีในขณะทำงาน ผู้คนก็จะเลิกเขียน tests และงานก็จะช้าลง

อีกทางเลือกหนึ่งคือเก็บ production code และ test code ไว้ในตำแหน่งเดียวกัน แต่ใช้ scripts หรือ build settings เพื่อเอา test code ออกจาก deployment ถ้าคุณใช้ naming conventions ที่ดีสำหรับคลาสของคุณ วิธีนี้ก็ใช้ได้ดี

เหนือสิ่งอื่นใด ถ้าคุณเลือกที่จะแยก test และ production code ให้แน่ใจว่ามันมีเหตุผลที่ดี บ่อยครั้งที่ทีมแยกโค้ดด้วยเหตุผลด้านความสวยงามล้วนๆ: พวกเขาแค่ทนไม่ได้กับความคิดที่จะวาง production code และ tests ไว้ด้วยกัน ต่อมาการนำทางในโปรเจกต์ก็จะกลายเป็นเรื่องปวดหัว คุณสามารถชินกับการมี tests อยู่ติดกับ production source ของคุณได้ หลังจากทำงานแบบนั้นไปสักพัก มันก็จะรู้สึกเป็นปกติ