自動的自動化:智能化測試框架EvoSuite的一個TooManyResourceException處理方法
問題
最近在不斷地學習和探索EvoSuite框架的時候,在生產JUnit單元測試框架後,出現如下問題:
Exception:
Caused by: org.evosuite.runtime.TooManyResourcesException: Loop has been executed more times than the allowed 10000
at org.evosuite.runtime.LoopCounter.checkLoop(LoopCounter.java:115)
at org.apache.xerces.impl.io.UTF8Reader.read(Unknown Source)
at org.apache.xerces.impl.XMLEntityScanner.load(Unknown Source)
at org.apache.xerces.impl.XMLEntityScanner.skipSpaces(Unknown Source)
at org.apache.xerces.impl.XMLDocumentScannerImpl$PrologDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:121)
at org.apache.poi.util.DocumentHelper.readDocument(DocumentHelper.java:137)
at org.apache.poi.POIXMLTypeLoader.parse(POIXMLTypeLoader.java:115)
at org.openxmlformats.schemas.spreadsheetml.x2006.main.StyleSheetDocument$Factory.parse(Unknown Source)
at org.apache.poi.xssf.model.StylesTable.readFrom(StylesTable.java:203)
at org.apache.poi.xssf.model.StylesTable.(StylesTable.java:146)
分析和修訂
所有的EvoSuite生成的單元測試class都繼承自一個同名的scaffolding的類,在對應的腳手架後綴名的類中的@BeforeClass部分,有一個參數:
org.evosuite.runtime.RuntimeSettings.maxNumberOfIterationPerLoop=10000;
上述報錯就是因爲這一項的設置造成的。那麼該org.evosuite.runtime.RuntimeSettings.maxNumberOfIterationPerLoop是幹什麼的呢?這裏我們就要進入EvoSuite的源代碼裏面看看了。
經過源代碼分析,在源代碼中:
evosuite/runtime/src/main/java/org/evosuite/runtime/LoopCounter.java
發現其110行到123行部分能夠拋出對應的異常,依據作者註釋,該類就是爲了避免無限循環的出現而專門做的一個循環計數的類。通過源代碼的異常拋出位置可以看出就是一位代碼執行的循環次數超過了10000而拋出的異常,這麼大次數的循環有可能是mock的數據導致的,也有可能是內部腳本邏輯異常導致的。
解決該問題
通過對應github項目的查找發現這不是一個fixed的issue。但是可以通過設置該參數避免該異常出現。
通過maxNumberOfIterationPerLoop出現的條件部分的判斷:
evosuite/runtime/src/main/java/org/evosuite/runtime/LoopCounter.java的96到98行,如下:
if(RuntimeSettings.maxNumberOfIterationsPerLoop < 0){
return; //do nothing, no check
}
和/Users/chancriss/Desktop/WorkSpace/JavaSpace/github/evosuite/runtime/src/main/java/org/evosuite/runtime/instrumentation/RuntimeInstrumentation.java下的144行到146行,如下:
if (RuntimeSettings.maxNumberOfIterationsPerLoop >= 0) {
cv = new LoopCounterClassAdapter(cv);
}
可知,要避免這類問題的出現,並不是在對應的JUnit腳本的父類中擴大org.evosuite.runtime.RuntimeSettings.maxNumberOfIterationPerLoop的值,而是將其設置成爲一個小於0的值。
由於測者並沒有完全掌握該框架,因此這種的修改到底會帶來什麼後果還沒有進一步的研究。