‫تجاربی از CI و Automatic Unit Testing با TeamCity

به سلامتی TeamCity را به قصد راه اندازی CI و انجام خودکار Unit Testها راه انداختیم اما مشکلات و مسائل زیادی به وجود آمد. بعضی‌ها حل شدند و بعضی‌ها نه. خلاصه‌ای از نکاتی که به آن برخورد کردم:

۱- نصب خود TeamCity خیلی ساده و سریع بود. ولی تا آنجا که فهمیدم فقط با MSBuild می‌شود با آن کار کرد و مثل TFS نیست که بشود با WorkFlow آن کارهای اضافی کرد.

۲- با آن که از git استفاده می‌کنیم ولی خوشبختانه مسائل ارتباط با git خیلی خیلی کمتر از آنی بود که فکر می‌کردم. حتی بخش CI که بایستی با push کردن هر تغییر تریگر شود بدون کمترین مشکلی کار کرد (اقلاً مشکل خاصی حس نکردم).

۳- معرفی Build Agentها به دلایلی مثل روشن بودن فایروال، نبودن git در مسیر اجرایی ویندوز و غیره اذیت کرد ولی نه خیلی.

۴- مشکل NuGet فوق‌العاده شدید بود. به راحتی آب خوردن یکی دو روز از وقتم را گرفت. با آن که تنظیم کرده بودم که دریافت packageها خودکار باشد ولی TeamCity با آن که packageها را دریافت می‌کرد باز هم build error می‌داد. به عنوان یک راه حل موقتی فایل‌های packageها را دستی در Build Agentها کپی کردم. ولی بعد از کش و قوس‌های فراوان تصمیم گرفتم NuGet را کنار بگذارم و همه Assemblyها مورد نیاز در داخل سورس کنترل اضافه کنم.

۵- مشکل بعدی مربوط به build target در یکی از Agentها بود. اول فکر کردم مشکل به خاطر نصب نبودن MVC 3 (پروژه مورد استفاده ما MVC 3 است) در agent است. اما متوجه شدم آنجام MVC 3 نصب هست و احتمالا مشکل از نصب نبودن Visual Studio 2010 در آنجا است. به هر صورت تصمیم گرفتم کمی کثیف کاری کنم (راه بهتری پیدا نکردم) و فایل ‎.targets مربوطه به agent مشکل دار کپی کنم.

۶- قدم بعدی انجام اتوماتیک Unit Testها بود. تنظیم آن محدود به یک Build Step ساده بود ولی در اولین قدم معرفی اسمبلی حاوی test کمی مشکل ایجاد کرد که با کمی سعی و خطا حل شد. اگر ساختار فولدر پروژه عوض شود باید آن را هم به روز رسانی کنم.

۷- مشکل Unit Test محدود به مشکل قبلی نبود. در یکی Agentها که ۶۴ بیتی بود، Unit Testها Run نمی‌شدند. در Unit Testهای مورد اشاره، عملیات دیتابیسی با استفاده دیتابیس داخل حافظه‌ای SQLite تست می‌شد. یادم آمد که SQLite دو نسخه مجزا برای محیط‌های ۳۲ بیتی و ۶۴ بیتی دارد. باید راهی پیدا می‌کردم تا Testها هم در ماشین ۳۲ بیتی اجرا شوند و هم در ماشین ۶۴ بیتی. تازه ماشین‌های development هم همگی ۳۲ بیت بودند و نباید یکپارچگی را از دست می‌دادم. مناسب‌ترین راه حل این بود که در زمان اجرا (Run Time) تشخیص می‌دادم که محیط ۳۲ یا ۶۴ بیتی است و بعد اسمبلی متناظر را به application اضافه می‌کردم. این راه زیادی Low Level بود. یک راه دیگر استفاده از GAC بود. اما من نهایتاً یک راه ساده و کثیف را (اقلا موقتی) انتخاب کردم. نسخه ۶۴ بیتی SQLite را دستی در فولدر Work (مسیر خاص پروژه من) کپی کردم و مشکل حل شد. حالا کل سیستم ۳۲ بیت بود ولی آن Agent خاص برای انجام Unit Testها از نسخه ۶۴ بیت خودش استفاده می‌کرد.