يوفر المكون الإضافي القدرة على إجراء اختبار طفرة وحساب تغطية طفرة للمشاريع القائمة على Gradle مع Pit.
أضف Gradle-pitest-plugin إلى تكوين plugins في ملف build.gradle :
plugins {
id ' java ' // or 'java-library' - depending on your needs
id ' info.solidsoft.pitest ' version ' 1.15.0 '
}plugins {
id( " java " ) // or "java-library" - depending on your needs
id( " info.solidsoft.pitest " ) version " 1.15.0 "
}استدعاء Gradle بمهمة Pitest:
gradle pitest
بعد القياسات ، سيتم وضع تقرير تم إنشاؤه بواسطة PIT في دليل ${PROJECT_DIR}/build/reports/pitest .
اختياريا اجعله يعتمد على البناء:
build . dependsOn ' pitest 'tasks.build {
dependsOn( " pitest " )
} لاحظ أنه عند جعل pitest يعتمد على مهمة أخرى ، يجب الإشارة إليها بالاسم. خلاف ذلك ، سوف يحل Gradle pitest إلى التكوين وليس المهمة.
"طريقة plugins " لها بعض القيود. نظرًا لأن المستودع الأساسي للمكون الإضافي هو المستودع المركزي (ويعرف أيضًا باسم Maven Central) ، فمن الممكن أيضًا إضافة المكون الإضافي إلى مشروعك باستخدام "الطريقة العامة":
buildscript {
repositories {
mavenCentral()
// Needed only for SNAPSHOT versions
// maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
}
dependencies {
classpath ' info.solidsoft.gradle.pitest:gradle-pitest-plugin:1.15.0 '
}
}buildscript {
repositories {
mavenCentral()
// Needed only for SNAPSHOT versions
// maven {
// url = uri("https://oss.sonatype.org/content/repositories/snapshots/")
// }
}
dependencies {
classpath( " info.solidsoft.gradle.pitest:gradle-pitest-plugin:1.15.0 " )
}
}تطبيق البرنامج المساعد:
apply plugin : ' java ' // or 'java-library' - depending on your needs
apply plugin : ' info.solidsoft.pitest ' apply (plugin = " java " ) // or "java-library" - depending on your needs
apply (plugin = " info.solidsoft.pitest " ) لا يلزم تكوين المكون الإضافي Pitest بشكل إضافي إذا كنت تستخدم Junit 4. تتم التخصيص في كتلة pitest :
pitest {
targetClasses = [ ' our.base.package.* ' ] // by default "${project.group}.*"
pitestVersion = ' 1.15.0 ' // not needed when a default PIT version should be used
threads = 4
outputFormats = [ ' XML ' , ' HTML ' ]
timestampedReports = false
}التكوين الاصطلاحي والمزيد من المحمولة:
pitest {
targetClasses.set( setOf ( " our.base.package.* " )) // by default "${project.group}.*"
pitestVersion.set( " 1.15.0 " ) // not needed when a default PIT version should be used
threads.set( 4 )
outputFormats.set( setOf ( " XML " , " HTML " ))
timestampedReports.set( false )
} بدءًا من Gradle 8.1 يمكن استخدام تعيين خاصية بسيطة لتكوين البرنامج المساعد (بدلاً من طريقة set() ):
pitest {
targetClasses = setOf ( " our.base.package.* " ) // by default "${project.group}.*"
pitestVersion = " 1.15.0 " // not needed when a default PIT version should be used
threads = 4
outputFormats = setOf ( " XML " , " HTML " )
timestampedReports = false
} التكوين في Gradle هو الرمز الرائع الحقيقي الذي يجعل جميع المهام بديهية للغاية. يجب تمرير جميع القيم المتوقعة بواسطة PIT كنوع مقابل. لا يوجد سوى اختلاف مهم واحد. بالنسبة للمعلمات التي تتوقع فيها PIT قائمة مفصولة بالغيبوبة من السلاسل في تكوين Gradle ، يجب استخدام قائمة بالسلاسل (انظر outputFormats في المثال أعلاه).
تحقق من وثائق الحفرة للحصول على قائمة بجميع معلمات سطر الأوامر المتاحة. يمكن أخذ تنسيق المعلمة المتوقع في تكوين البرنامج المساعد من PiteStpluginextension.
لجعل الحياة أسهل taskClasspath ، يتم تعيين mutableCodePaths ، sourceDirs ، reportDir ، verbosity pitestVersion تلقائيًا بواسطة المكون الإضافي. بالإضافة إلى ذلك ، يمكن التغلب على sourceDirs و reportDir و verbosity و pitestVersion من قبل المستخدم.
هناك عدد قليل من المعلمات المحددة لمكوّن الإضافات Gradle:
testSourceSets - يحدد مجموعات مصدر الاختبار التي يجب استخدامها بواسطة Pit (بشكل افتراضي المصادر.mainSourceSets - يحدد مجموعات المصادر الرئيسية التي يجب استخدامها بواسطة PIT (بشكل افتراضي المصادر.mainProcessJvmArgs - JVM الحجج المراد استخدامها عند إطلاق عملية الحفرة الرئيسية ؛ لاحظ أن Pit نفسها تطلق عمليات Java أخرى لتنفيذ اختبار الطفرة وعادة ما يجب استخدام jvmArgs لزيادة الحد الأقصى لحجم الذاكرة (انظر #7) ؛additionalMutableCodePaths - فئات إضافية للتحول (مفيدة لاختبارات التكامل مع رمز الإنتاج في وحدة مختلفة - انظر #25)useClasspathFile - يتيح تمرير ClassPath إضافي كمحتوى ملف (مفيد لمستخدمي Windows مع الكثير من عناصر ClassPath ، معطل بشكل افتراضي)fileExtensionsToFilter - يوفر القدرة على تصفية ملحقات الملف الإضافية من Pit ClassPath (انظر #53)على سبيل المثال:
pitest {
.. .
testSourceSets = [sourceSets . test, sourceSets . integrationTest]
mainSourceSets = [sourceSets . main, sourceSets . additionalMain]
jvmArgs = [ ' -Xmx1024m ' ]
useClasspathFile = true // useful with bigger projects on Windows
fileExtensionsToFilter . addAll( ' xml ' , ' orbit ' )
}pitest {
.. .
testSourceSets.set( listOf (sourceSets.test.get(), sourceSets.getByName( " integrationTest " )))
mainSourceSets.set( listOf (sourceSets.main.get(), sourceSets.getByName( " additionalMain " )))
jvmArgs.set( listOf ( " -Xmx1024m " ))
useClasspathFile.set( true ) // useful with bigger projects on Windows
fileExtensionsToFilter.addAll( " xml " , " orbit " )
}تنفذ PIT الاختبارات في JVM مستقلة عن JVM المستخدمة بواسطة Gradle لتنفيذ الاختبارات. إذا كانت اختباراتك تتطلب بعض خصائص النظام ، فيجب عليك تمريرها إلى الحفرة لأن المكون الإضافي لن يفعل ذلك من أجلك:
test {
systemProperty ' spring.test.constructor.autowire.mode ' , ' all '
}
pitest {
jvmArgs = [ ' -Dspring.test.constructor.autowire.mode=all ' ]
}tasks.test {
systemProperty( " spring.test.constructor.autowire.mode " , " all " )
}
pitest {
jvmArgs.set( listOf ( " -Dspring.test.constructor.autowire.mode=all " ))
} كما ورد في #170 يعرض Idea Idea تحذيرات حول وضع الحقول النهائية (من التكوين البطيء) في build.gradle . إنها ليست مشكلة حقيقية حيث يعترض Gradle داخليًا تلك المكالمات واستخدام Setter بدلاً من ذلك. ومع ذلك ، يمكن للأشخاص الذين يفضلون عدم وجود تحذيرات (أقل) على حساب الكود الأقل قابلية للقراءة استخدام المستقلين بدلاً من ذلك ، على سبيل المثال:
testSourceSets . set([sourceSets . test, sourceSets . integrationTest])
mainSourceSets . set([sourceSets . main, sourceSets . additionalMain])
jvmArgs . set([ ' -Xmx1024m ' ])
useClasspathFile . set( true ) // useful with bigger projects on Windows
fileExtensionsToFilter . addAll( ' xml ' , ' orbit ' )يمكن استخدام Gradle-pitest-Plugin في مشاريع متعددة الوحدات. يجب إضافة تبعية Gradle-pit-Pit-Plugin إلى تكوين BuildScript في مشروع الجذر بينما يجب تطبيق المكون الإضافي في جميع المشروعات الفرعية التي يجب معالجتها باستخدام PIT. عينة مقتطف من Build.gradle الموجودة لمشروع الجذر:
// in root project configuration
plugins {
id ' info.solidsoft.pitest ' version ' 1.15.0 ' apply false
}
subprojects {
apply plugin : ' java '
apply plugin : ' info.solidsoft.pitest '
pitest {
threads = 4
if (project . name in [ ' module-without-any-test ' ]) {
failWhenNoMutations = false
}
}
} // in root project configuration
plugins {
id( " info.solidsoft.pitest " ) version " 1.15.0 "
}
subprojects {
apply (plugin = " java " )
apply (plugin = " info.solidsoft.pitest " )
pitest {
threads.set( 4 )
if (project.name in setOf ( " module-without-any-test " )) {
failWhenNoMutations.set( false )
}
}
} من الممكن تجميع تقرير pitest للمشروع متعدد الوحدات باستخدام info.solidsoft.pitest.aggregator و Task pitestReportAggregate . يجب تكوين مشروع الجذر بشكل صحيح لاستخدام pitestReportAggregate :
// in root project configuration
plugins {
id ' info.solidsoft.pitest ' version ' 1.15.0 ' apply false
}
apply plugin : ' info.solidsoft.pitest.aggregator ' // to 'pitestReportAggregate' appear
subprojects {
apply plugin : ' java '
apply plugin : ' info.solidsoft.pitest '
pitest {
// export mutations.xml and line coverage for aggregation
outputFormats = [ " XML " ]
exportLineCoverage = true
timestampedReports = false
.. .
reportAggregator { // since 1.9.11 - extra results validation, if needed
testStrengthThreshold . set( 50 ) // simpler Groovy syntax (testStrengthThreshold = 50) does not seem to be supported for nested properties
mutationThreshold . set( 40 )
maxSurviving . set( 3 )
}
}
} // in root project configuration
plugins {
id( " info.solidsoft.pitest " ) version " 1.15.0 "
}
apply (plugin = " info.solidsoft.pitest.aggregator " )
subprojects {
apply (plugin = " java " )
apply (plugin = " info.solidsoft.pitest " )
pitest {
outputFormats.set( setOf ( " XML " ))
timestampedReports.set( false )
exportLineCoverage.set( true )
.. .
reportAggregator {
testStrengthThreshold.set( 50 )
mutationThreshold.set( 40 )
maxSurviving.set( 3 )
}
}
} بعد تنفيذ مهام pitest pitestReportAggregate ، سيتم وضع التقرير المجمعة في دليل ${PROJECT_DIR}/build/reports/pitest .
من الممكن تحوير التعليمات البرمجية الموجودة في المشاريع الفرعية المختلفة. لا يعتمد Gradle داخليًا على دليل الإخراج من المشروع الفرعي الآخر ، ولكنه يبني جرة ويستخدم فئات منه. بالنسبة إلى PIT هذان مجموعتان مختلفتان من ملفات الفصل ، لذلك لجعلها تعمل ، يجب أن تحدد كل من mainSourceSets و additionalMutableCodePaths . على سبيل المثال:
configure(project( ' :itest ' )) {
apply plugin : ' info.solidsoft.pitest '
dependencies {
implementation project( ' :shared ' )
}
configurations { mutableCodeBase { transitive false } }
dependencies { mutableCodeBase project( ' :shared ' ) }
pitest {
mainSourceSets = [project . sourceSets . main, project( ' :shared ' ) . sourceSets . main]
additionalMutableCodePaths = [configurations . mutableCodeBase . singleFile]
}
}configure( listOf (project( " :itest " ))) {
apply (plugin = " info.solidsoft.pitest " )
dependencies {
implementation(project( " :shared " ))
}
val mutableCodeBase by configurations.creating { isTransitive = false }
dependencies { mutableCodeBase(project( " :shared " )) }
pitest {
mainSourceSets.set( listOf (project.sourceSets.main.get(), project( " :shared " ).sourceSets.main.get()))
additionalMutableCodePaths.set( listOf (mutableCodeBase.singleFile))
}
}ما سبق هو الطريقة التي يوصى بها فريق Gradle ، ولكن في حالات محددة يجب أن يعمل الحل الأبسط أيضًا:
configure(project( ' :itest ' )) {
apply plugin : ' info.solidsoft.pitest '
dependencies {
implementation project( ' :shared ' )
}
pitest {
mainSourceSets = [project . sourceSets . main, project( ' :shared ' ) . sourceSets . main]
additionalMutableCodePaths = project( ' :shared ' ) . jar . outputs . files . getFiles()
}
}configure( listOf (project( " :itest " ))) {
apply (plugin = " info.solidsoft.pitest " )
dependencies {
implementation(project( " :shared " ))
}
pitest {
mainSourceSets.set( listOf (project.sourceSets.main.get(), project( " :shared " ).sourceSets.main.get()))
additionalMutableCodePaths.set(project( " :shared " ).task( " jar " ).outputs.files)
}
}الحد الأدنى من العمل متعدد المشروع متاح في جناح الاختبارات الوظيفية.
يتم استخدام الإضافات الاختبار لدعم أطر الاختبار المختلفة عن JUNIT4.
بدءًا من هذا الإصدار ، تم تبسيط التكوين المطلوب لاستخدام Pit مع Junit 5 إلى ما يلي:
plugins {
id ' java '
id ' info.solidsoft.pitest ' version ' 1.15.0 '
}
pitest {
// adds dependency to org.pitest:pitest-junit5-plugin and sets "testPlugin" to "junit5"
junit5PluginVersion = ' 1.0.0 ' // or 0.15 for PIT <1.9.0
// ...
}plugins {
id( " java " )
id( " info.solidsoft.pitest " ) version " 1.15.0 "
}
pitest {
// adds dependency to org.pitest:pitest-junit5-plugin and sets "testPlugin" to "junit5"
junit5PluginVersion.set( " 1.0.0 " )
}يرجى الملاحظة . PIT 1.9.0 يتطلب pitest-junit5-plugin 1.0.0+. يتطلب Junit Jupiter 5.8 (Junit Platform 1.8) pitest-junit5-plugin 0.15+ ، بينما يتطلب 5.7 (1.7) 0.14. قم بتعيين إصدار مكون الإضافي الأيمن لإصدار Junit 5 المستخدم في مشروعك لتجنب أخطاء وقت التشغيل (مثل `nosuchmethoderror: 'java.util.optional org.junit.platform.commons.util.annotationutils.findannotation (java.lang.class ، java.lang.class ، boolean)').
يتوفر مثال العمل الحد الأدنى لـ Junit 5 في جناح الاختبارات الوظيفية.
لخلط Junit 5 مع الإضافات الأخرى ، يمكنك قراءة هذا القسم في منشور مدونتي.
لتمكين المكونات الإضافية للحفر ، يكفي إضافتها إلى التكوين الأكثر روعة في إغلاق BuildScript. على سبيل المثال:
plugins {
id ' java '
id ' info.solidsoft.pitest ' version ' 1.15.0 '
}
repositories {
mavenCentral()
}
dependencies {
pitest ' org.example.pit.plugins:pitest-custom-plugin:0.42 '
}plugins {
id( " java " )
id( " info.solidsoft.pitest " ) version " 1.15.0 "
}
repositories {
mavenCentral()
}
dependencies {
pitest( " org.example.pit.plugins:pitest-custom-plugin:0.42 " )
}يتوفر مثال العمل الحد الأدنى في جناح الاختبارات الوظيفية.
يرجى الملاحظة. في Gradle-pitest-plugin <1.5.0 ، كان يجب إنشاء التكوين pitest في نطاق buildscript لمشروع الجذر. يرجى الملاحظة. بدءًا من Pit 1.6.7 ، لم يعد هناك حاجة لضبط معلمة تكوين testPlugin . كما أنه يتم إهماله في البرنامج المساعد Gradle.
يستخدم كل إصدار Gradle-pitest-Plugin افتراضيًا إصدارًا محددًا مسبقًا. عادةً ما يكون هذا الإصدار الذي تم إصداره من PIT متاحًا في وقت إصدار إصدار مكون إضافي. يمكن تجاوزه باستخدام معلمة pitestVersion في إغلاق pitest .
يرجى العلم أنه في بعض الحالات ، قد تكون هناك بعض المشكلات عند استخدام إصدارات PIT غير الافتراضية.
إذا لم يذكر خلاف ذلك ، فإن Gradle-pitest-Plugin 1.9.x يستخدم افتراضيًا Pit 1.9.x ، 1.7.x يستخدم Pit 1.7.x ، إلخ. إصدار الحفرة المدعوم هو 1.7.1.
بدءًا من الإصدار 1.7.0 Gradle-pitest-Plugin يتطلب Gradle 6.4. أحدث إصدار مع دعم Gradle 5.x (5.6+) هو 1.6.0. تم تلقائيًا تم اختبار الإصدار الحالي مع Gradle 6.4 و 6.9.1 و 7.4.2 تحت Java 11. اختبارات مع Java 11+ تقتصر على الإصدارات المتوافقة من Gradle و Pit.
يمكن اختبار الدعم التجريبي لـ Java 17 باستخدام 1.7.0+.
بدءًا من الإصدار 1.3.0 ، تتطلب الثنائيات المنتجة java 8 (كـ JDK المستخدمة في تشغيل بنية Gradle). ومع ذلك ، بعد إصدار Java 17 LTS في سبتمبر 2021 ، بدءًا من Gradle-Pitest-Plugin 1.9.0 ، يتم إهمال دعم JDK <11 (انظر #299).
راجع ملف Changelog للحصول على قائمة أكثر تفصيلاً من التغييرات في البرنامج المساعد نفسه.
لا يوفر Gradle طريقة مدمجة لتجاوز تكوين البرنامج المساعد عبر سطر الأوامر ، ولكن يمكن استخدام Gradle-Override-Plugin للقيام بذلك.
بعد تطبيق Gradle-Override-Plugin في مشروعك ، من الممكن القيام بمتابعة:
./gradlew pitest -Doverride.pitest.reportDir=build/pitReport -Doverride.pitest.threads=8
ملحوظة. يجب أن تعمل الآلية بشكل جيد لخصائص السلسلة والرقمية ، ولكن هناك قيود على دعم القوائم/المجموعات/الخرائط والقيم المنطقية.
لمزيد من المعلومات ، انظر صفحة الويب للمشروع.
يستخدم Gradle-pitest-Plugin افتراضيًا إصدار حفرة مقابل (بنفس الرقم). يتم إصدار المكون الإضافي فقط إذا كانت هناك تغييرات داخلية أو هناك حاجة إلى التكيف مع التغييرات في إصدار PIT الأحدث. هناك آلية مخصصة للسماح باستخدام أحدث إصدار من الحفرة (على سبيل المثال ، إصدار BugFix) أو لخفض الحفرة في حالة وجود مشكلات تم اكتشافها. لتجاوز الإصدار الافتراضي ، يكفي تعيين خاصية pitestVersion في إغلاق pitest .
pitest {
pitestVersion = ' 2.8.1-the.greatest.one '
}pitest {
pitestVersion.set( " 2.8.1-the.greatest.one " )
}في حالة اكتشاف الأخطاء التي تم اكتشافها عند استخدام أحدث إصدار متاح من المكون الإضافي مع إصدار Pit الجديد ، يرجى إثارة مشكلة.
يمكن تمكين وضع تقارير PIT مباشرة في ${PROJECT_DIR}/build/reports/pitest باستخدام خاصية تكوين timestampedReports :
pitest {
timestampedReports = false
}pitest {
timestampedReports.set( false )
}في بعض الأحيان ، قد يكون من المفيد تصحيح تنفيذ Gradle-Pitest-Plugin أو تنفيذ الحفرة نفسه (على سبيل المثال NPE في PIT) لتوفير تقرير خطأ معقول.
يمكن تصحيح تنفيذ Gradle-pitest-plugin عن بُعد مع إضافة -Dorg.gradle.debug=true إلى سطر الأوامر.
ومع ذلك ، حيث يتم بدء PIT كعملية منفصلة لتصحيح تنفيذها ، يجب إضافة الوسائط التالية إلى تكوين المكون الإضافي:
pitest {
mainProcessJvmArgs = [ ' -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005 ' ]
}pitest {
mainProcessJvmArgs.set( listOf ( " -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005 " ))
}الجواب القصير هو: ليس مباشرة. نظرًا لبعض عدم التوافق بين تطبيقات Java "القياسية" وتطبيقات Android Java في Gradle ، لا يدعم المكون الإضافي لاحقًا. لحسن الحظ ، هناك شوكة Android للمكون الإضافي الذي تحتفظ به Karol Wrótniak والذي يوفر نسخة معدلة تدعم تطبيقات Android (ولكن من ناحية أخرى ، لا تعمل مع تطبيقات Java القياسية).
غادرت Gradle-Pitest Plugin 1.5.0 أخيرًا الطريقة التي تم بها (حيث) تكوين pitest (#62) الذي كان يولد أيضًا تحذيرات إهمال في Gradle 6+. هذا التغيير غير متوافق للخلف ، ونتيجة لذلك ، يجب إجراء ترحيل يدوي - انظر ملاحظات الإصدار. هذا يؤثر فقط على المشروع مع الإضافات المخصصة الخارجية.
مهم . نظرًا لأن المكون الإضافي JUNIT 5 لـ PIT هو بالتأكيد الأكثر شعبية ، بدءًا من 1.4.7 ، هناك طريقة مبسطة لكيفية تكوينها باستخدام junit5PluginVersion ( الموصى بها بالتأكيد). راجع منشور مدونتي لمعرفة كيفية الترحيل (كما أنه يحل مشكلة التوافق مع 1.5.0+).
verbosity الذي تم تقديمه مع Pit 1.7.1) يمكن بناء Gradle-pitest-plugin من المستودع باستخدام أمر Gradle:
./gradlew build
أسهل طريقة لجعل جرة مع تغييرات محلية مرئية في مشروع آخر هي تثبيتها في مستودع Maven المحلي:
./gradlew install
هناك أيضًا اختبارات وظيفية أساسية مكتوبة باستخدام اختبار السديم الذي يمكن تشغيله مع:
./gradlew funcTest
كتب Gradle-pitest-Plugin بواسطة Marcin Zajączkowski بمساعدة من المساهمين. يمكن الاتصال بالمؤلف مباشرة عبر البريد الإلكتروني: mszpak att wp dott pl. تتوفر أيضًا مدونة Marcin: Solid Soft - رمز العمل لا يكفي.
من المؤكد أن المكون الإضافي يحتوي على بعض الأخطاء والميزات المفقودة. يمكن الإبلاغ عنها باستخدام متتبع مشكلة. ومع ذلك ، فغالبًا ما يكون من الأفضل إرسال أسئلة إلى القائمة البريدية للحفرة أولاً.
المكون الإضافي مرخص له بموجب شروط ترخيص Apache ، الإصدار 2.0.