تمرين - إصلاح اختبار فاشل
عند هذه النقطة، لديك طريقة لتشغيل اختبارات الوحدة مع انتقال التغييرات عبر البنية الأساسية لبرنامج ربط العمليات التجارية للبناء. لديك أيضا طريقة لقياس مقدار التعليمات البرمجية التي تغطيها اختباراتك.
من الجيد دائما إجراء اختباراتك محليا قبل إرسال التغييرات إلى البنية الأساسية لبرنامج ربط العمليات التجارية. ولكن ماذا يحدث عندما ينسى شخص ما ويرسل تغييرا يكسر البنية؟
في هذه الوحدة، ستقوم بإصلاح بنية مقطوعة ناتجة عن اختبار وحدة فاشل. من هنا، سيمكنك:
- احصل على رمز البداية من GitHub.
- إضافة أدوات تغطية التعليمات البرمجية إلى مشروعك.
- ادفع التعليمات البرمجية إلى المستودع الخاص بك.
- شاهد تشغيل البنية الأساسية لبرنامج ربط العمليات التجارية تلقائيا وفشل اختبارات الوحدة.
- إعادة إنتاج الفشل محليا.
- تحليل الفشل وإصلاحه.
- دفع الإصلاح ومشاهدة نجاح البنية.
مراجعة اختبار الوحدة الجديد
تتضمن أحدث ميزات الفريق لوحة المتصدرين. نحتاج إلى الحصول على عدد النقاط من قاعدة البيانات، حتى نتمكن من كتابة اختبار وحدة للتحقق من IDocumentDBRepository<T>.GetItemsAsync
الأسلوب.
إليك الشكل الذي يبدو عليه الاختبار. لا تحتاج إلى إضافة أي تعليمات برمجية حتى الآن.
[TestCase(0, ExpectedResult=0)]
[TestCase(1, ExpectedResult=1)]
[TestCase(10, ExpectedResult=10)]
public int ReturnRequestedCount(int count)
{
const int PAGE = 0; // take the first page of results
// Fetch the scores.
Task<IEnumerable<Score>> scoresTask = _scoreRepository.GetItemsAsync(
score => true, // return all scores
score => 1, // we don't care about the order
PAGE,
count // fetch this number of results
);
IEnumerable<Score> scores = scoresTask.Result;
// Verify that we received the specified number of items.
return scores.Count();
}
تذكر أنه في اختبار NUnit، TestCase
يوفر بيانات مضمنة لاستخدامها لاختبار هذا الأسلوب. يستدعي ReturnRequestedCount
NUnit أسلوب اختبار الوحدة كما يلي:
ReturnRequestedCount(0);
ReturnRequestedCount(1);
ReturnRequestedCount(10);
يستخدم هذا الاختبار أيضا الخاصية ExpectedResult
لتبسيط التعليمات البرمجية للاختبار والمساعدة في توضيح نيته. يقارن NUnit تلقائيا القيمة المرجعة مقابل قيمة هذه الخاصية، مما يزيل الحاجة إلى استدعاء التأكيد بشكل صريح.
سنختار بعض القيم التي تمثل الاستعلامات النموذجية. سنقوم أيضا بتضمين 0 لتغطية حالة الحافة هذه.
إحضار الفرع من GitHub
كما فعلت سابقا، أحضر failed-test
الفرع من GitHub وتحقق (أو قم بالتبديل إلى) هذا الفرع.
في Visual Studio Code، افتح المحطة الطرفية المتكاملة.
git fetch
قم بتشغيل الأوامر التالية وgit checkout
لتنزيل فرع يسمىfailed-test
من مستودع Microsoft والتبديل إلى هذا الفرع:git fetch upstream failed-test git checkout -B failed-test upstream/failed-test
لقد أطلقنا على الفرع
failed-test
اسما لأغراض التعلم. في الممارسة العملية، يمكنك تسمية فرع بعد الغرض منه أو الميزة الخاصة به.قم بتشغيل هذه الأوامر لإنشاء ملف بيان أداة محلي وتثبيت
ReportGenerator
الأداة وإضافة الحزمةcoverlet.msbuild
إلى مشروع الاختبارات:dotnet new tool-manifest dotnet tool install dotnet-reportgenerator-globaltool dotnet add Tailspin.SpaceGame.Web.Tests package coverlet.msbuild
تحتاج إلى هذه الخطوة لأن الإصدار الفرعي
failed-test
لا يحتوي على العمل الذي أضفته إلى الإصدار الفرعيunit-tests
.أضف ملف مشروع الاختبار وملف بيان الأداة إلى الفهرس المرحلي وقم بتثبيت التغييرات.
git add Tailspin.SpaceGame.Web.Tests/Tailspin.SpaceGame.Web.Tests.csproj git add .config/dotnet-tools.json git commit -m "Configure code coverage tests"
قم بتشغيل الأمر التالي
git push
لتحميلfailed-test
الفرع إلى مستودع GitHub الخاص بك:git push origin failed-test
راجع فشل الاختبار في البنية الأساسية لبرنامج ربط العمليات التجارية
لنفترض أنك كنت في عجلة من أمرك ودفعت عملك دون إجراء الاختبارات مرة أخيرة. لحسن الحظ، يمكن أن تساعدك البنية الأساسية لبرنامج ربط العمليات التجارية في التقاط المشكلات في وقت مبكر عند وجود اختبارات الوحدة. يمكنك أن ترى ذلك هنا.
في Azure Pipelines، تتبع البنية أثناء تشغيلها عبر البنية الأساسية لبرنامج ربط العمليات التجارية.
قم بتوسيع تشغيل اختبارات الوحدة - مهمة الإصدار أثناء تشغيلها.
ترى أن
ReturnRequestedCount
أسلوب الاختبار يفشل.يمر الاختبار عندما تكون قيمة الإدخال 0، ولكنها تفشل عندما تكون قيمة الإدخال 1 أو 10.
يتم نشر البنية إلى البنية الأساسية لبرنامج ربط العمليات التجارية فقط عند نجاح المهمة السابقة. هنا، لم يتم نشر البنية بسبب فشل اختبارات الوحدة. وهذا يمنع الآخرين من الحصول على بنية مقطوعة عن طريق الخطأ.
في الممارسة العملية، لن تتبع دائما البنية يدويا أثناء تشغيلها. فيما يلي بعض الطرق التي قد تكتشف بها الفشل:
إعلام بالبريد الإلكتروني من Azure DevOps
يمكنك تكوين Azure DevOps لإرسال إشعار بالبريد الإلكتروني عند اكتمال الإنشاء. يبدأ سطر الموضوع ب "[فشل الإنشاء]" عند فشل البنية.
Azure Test Plans
في Azure DevOps، حدد Test Plans، ثم حدد Runs. ترى عمليات تشغيل الاختبار الأخيرة، بما في ذلك الاختبار الذي تم تشغيله للتو. حدد آخر اختبار مكتمل. ترى أن اختبارين من الاختبارات الثمانية فشلا.
لوحة المعلومات
في Azure DevOps، حدد Overview، ثم حدد Dashboards. ترى الفشل يظهر في عنصر واجهة مستخدم اتجاه نتائج الاختبار. إن عنصر واجهة المستخدم تغطية التعليمات البرمجية فارغ، ما يشير إلى عدم تشغيل تغطية التعليمات البرمجية.
شارة البناء
على الرغم من أن الفرع
failed-test
لا يتضمن شارة البناء في ملف README.md، فإليك ما ستراه على GitHub عندما يفشل البناء:
تحليل فشل الاختبار
عندما تفشل اختبارات الوحدة، يكون لديك عادة خياران، اعتمادا على طبيعة الفشل:
- إذا كشف الاختبار عن عيب في التعليمات البرمجية، فصحح التعليمات البرمجية وأعد تشغيل الاختبارات.
- إذا تغيرت الوظيفة، فاضبط الاختبار لمطابقة المتطلبات الجديدة.
إعادة إنتاج الفشل محليا
في هذا القسم، ستقوم بإعادة إنتاج الفشل محليا.
في Visual Studio Code، افتح المحطة الطرفية المتكاملة.
في المحطة الطرفية، قم بتشغيل هذا
dotnet build
الأمر لإنشاء التطبيق:dotnet build --configuration Release
في المحطة الطرفية، قم بتشغيل هذا
dotnet test
الأمر لتشغيل اختبارات الوحدة:dotnet test --no-build --configuration Release
يجب أن تشاهد نفس الأخطاء التي رأيتها في البنية الأساسية لبرنامج ربط العمليات التجارية. فيما يلي جزء من الإخراج:
Starting test execution, please wait... A total of 1 test files matched the specified pattern. Failed ReturnRequestedCount(1) [33 ms] Error Message: Expected: 1 But was: 0 Stack Trace: at NUnit.Framework.Internal.Commands.TestMethodCommand.Execute(TestExecutionContext context) at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.<>c__DisplayClass1_0.<Execute>b__0() at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.RunTestMethodInThreadAbortSafeZone(TestExecutionContext context, Action action) Failed ReturnRequestedCount(10) [1 ms] Error Message: Expected: 10 But was: 9 Stack Trace: at NUnit.Framework.Internal.Commands.TestMethodCommand.Execute(TestExecutionContext context) at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.<>c__DisplayClass1_0.<Execute>b__0() at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.RunTestMethodInThreadAbortSafeZone(TestExecutionContext context, Action action) Failed! - Failed: 2, Passed: 6, Skipped: 0, Total: 8, Duration: 98 ms
البحث عن سبب الخطأ
لاحظت أن كل اختبار فاشل ينتج نتيجة يتم إيقافها بمقدار واحد. على سبيل المثال، عند توقع 10، يقوم الاختبار بإرجاع 9.
ألق نظرة على التعليمات البرمجية المصدر للأسلوب الذي يتم اختباره، LocalDocumentDBRepository<T>.GetItemsAsync
. يجب أن تشاهد هذا:
public Task<IEnumerable<T>> GetItemsAsync(
Func<T, bool> queryPredicate,
Func<T, int> orderDescendingPredicate,
int page = 1, int pageSize = 10
)
{
var result = _items
.Where(queryPredicate) // filter
.OrderByDescending(orderDescendingPredicate) // sort
.Skip(page * pageSize) // find page
.Take(pageSize - 1); // take items
return Task<IEnumerable<T>>.FromResult(result);
}
في هذا السيناريو، يمكنك التحقق من GitHub لمعرفة ما إذا كان الملف قد تم تغييره مؤخرا.
أنت تشك في إرجاع pageSize - 1
نتيجة أقل وأن هذا يجب أن يكون فقط pageSize
. في السيناريو الخاص بنا، هذا خطأ قمت به عند دفع العمل دون اختبار، ولكن في سيناريو العالم الحقيقي، يمكنك التحقق من المطور الذي قام بتغيير الملف على GitHub لتحديد سبب التغيير.
تلميح
يمكن أن تحدث المناقشة والتعاون أيضا على GitHub. يمكنك التعليق على طلب سحب أو فتح مشكلة.
إصلاح الخطأ
في هذا القسم، ستقوم بإصلاح الخطأ عن طريق تغيير التعليمات البرمجية مرة أخرى إلى حالتها الأصلية وتشغيل الاختبارات للتحقق من الإصلاح.
في Visual Studio Code، افتح Tailspin.SpaceGame.Web/LocalDocumentDBRepository.cs من مستكشف الملفات.
GetItemsAsync
تعديل الأسلوب كما هو موضح هنا:public Task<IEnumerable<T>> GetItemsAsync( Func<T, bool> queryPredicate, Func<T, int> orderDescendingPredicate, int page = 1, int pageSize = 10 ) { var result = _items .Where(queryPredicate) // filter .OrderByDescending(orderDescendingPredicate) // sort .Skip(page * pageSize) // find page .Take(pageSize); // take items return Task<IEnumerable<T>>.FromResult(result); }
يتغير
pageSize - 1
هذا الإصدار إلىpageSize
.احفظ الملف.
في المحطة الطرفية المتكاملة، أنشئ التطبيق.
dotnet build --configuration Release
يجب أن ترى نجاح البنية.
في الممارسة العملية، يمكنك تشغيل التطبيق وتجربته لفترة وجيزة. لأغراض التعلم، سنتخطى ذلك في الوقت الحالي.
في المحطة الطرفية، قم بتشغيل اختبارات الوحدة.
dotnet test --no-build --configuration Release
ترى أن الاختبارات قد اجتزت.
Starting test execution, please wait... A total of 1 test files matched the specified pattern. Passed! - Failed: 0, Passed: 8, Skipped: 0, Total: 8, Duration: 69 ms
في المحطة الطرفية المتكاملة، أضف كل ملف معدل إلى الفهرس، وقم بتنفيذ التغييرات، وادفع الفرع إلى GitHub.
git add . git commit -m "Return correct number of items" git push origin failed-test
تلميح
النقطة (
.
) في هذاgit add
المثال هي حرف بدل. يطابق كافة الملفات غير المميزة في الدليل الحالي وجميع الدلائل الفرعية.قبل استخدام حرف البدل هذا، من الجيد تشغيله
git status
قبل الالتزام بالتأكد من أنك تقوم بتدريج الملفات التي تنوي تنظيمها.العودة إلى Azure Pipelines. شاهد التغيير يتحرك عبر البنية الأساسية لبرنامج ربط العمليات التجارية. تمر الاختبارات، وينجح البناء الكلي.
اختياريا، للتحقق من نتائج الاختبار، يمكنك تحديد علامات التبويب الاختبارات وتغطية التعليمات البرمجية عند اكتمال الإنشاء.
يمكنك أيضا التحقق من لوحة المعلومات لعرض اتجاه النتائج المحدثة.
عظيم! لقد قمت بإصلاح البنية. بعد ذلك، ستتعلم كيفية تنظيف بيئة Azure DevOps.