pharo-users@lists.pharo.org

Any question about pharo is welcome

View all threads

AI based test generation

KO
Kasper Osterbye
Thu, Feb 19, 2026 7:17 PM

Cheers

I am at the moment experimenting with getting an AI to write test methods for me.
The current results are a mixture of simple and advanced :-)

To get started I wanted to write tests for a class that does not go to the web, file or UI, and doing something which is standard, but with no method comments.

So the experiments is for the class "Heap".

I have not really been successful, but now I have what I see as a breakthrough, and wanted to know if anyone else had the same experience?

-- Kasper

Here is an example
Heap >> upHeap: anIndex
"Check the heap upwards for correctness starting at anIndex.
Everything below anIndex is ok."
| value k kDiv2 tmp |
anIndex = 0 ifTrue:[^self].
k := anIndex.
value := array at: anIndex.
[ (k > 1) and:[self sorts: value before: (tmp := array at: (kDiv2 := k bitShift: -1))] ]
whileTrue:[
array at: k put: tmp.
self updateObjectIndex: k.
k := kDiv2].
array at: k put: value.
self updateObjectIndex: k

And the test build by AI is this:
testUpHeap
| arr |
"Test upHeap: for index 0, should do nothing"
refHeap upHeap: 0.
self assert: true. "No error, no change expected"

"Set up min-heap sort block"
refHeap sortBlock: [ :a :b | a <= b ].

"Test upHeap:1 on single element, no change"
arr := Array new: 10.
arr at: 1 put: 5.
refHeap instVarAt: 1 put: arr.
refHeap instVarAt: 2 put: 1.
refHeap upHeap: 1.
self assert: ((refHeap instVarAt: 1) at: 1) equals: 5.

"Test upHeap:2 with swap needed (smaller child)"
arr := Array new: 10.
arr at: 1 put: 3.
arr at: 2 put: 1.
refHeap instVarAt: 1 put: arr.
refHeap instVarAt: 2 put: 2.
refHeap upHeap: 2.
self assert: ((refHeap instVarAt: 1) at: 1) equals: 1.
self assert: ((refHeap instVarAt: 1) at: 2) equals: 3.

"Test upHeap:2 with no swap (larger child)"
arr := Array new: 10.
arr at: 1 put: 3.
arr at: 2 put: 4.
refHeap instVarAt: 1 put: arr.
refHeap instVarAt: 2 put: 2.
refHeap upHeap: 2.
self assert: ((refHeap instVarAt: 1) at: 1) equals: 3.
self assert: ((refHeap instVarAt: 1) at: 2) equals: 4.

"Test upHeap:3 with one swap to root"
arr := Array new: 10.
arr at: 1 put: 3.
arr at: 2 put: 4.
arr at: 3 put: 2.
refHeap instVarAt: 1 put: arr.
refHeap instVarAt: 2 put: 3.
refHeap upHeap: 3.
self assert: ((refHeap instVarAt: 1) at: 1) equals: 2.
self assert: ((refHeap instVarAt: 1) at: 2) equals: 4.
self assert: ((refHeap instVarAt: 1) at: 3 )equals: 3.

"Test upHeap:4 with multiple swaps"
arr := Array new: 10.
arr at: 1 put: 1.
arr at: 2 put: 3.
arr at: 3 put: 2.
arr at: 4 put: 0.
refHeap instVarAt: 1 put: arr.
refHeap instVarAt: 2 put: 4.
refHeap upHeap: 4.
self assert: ((refHeap instVarAt: 1) at: 1) equals: 0.
self assert: ((refHeap instVarAt: 1) at: 2) equals: 1.
self assert: ((refHeap instVarAt: 1) at: 3) equals: 2.
self assert: ((refHeap instVarAt: 1) at: 4 )equals: 3.

And the input to make it doit is
AIATest04 new build: Heap >> #upHeap::

I have added a tool call that allows Grok to call and execute Pharo code, so to produce the test, it has executed these calls:

ApiToolExpression: Heap compileAllFrom: 'Collections-Sequenceable'. Heap methods select: [:m | m selector = #upHeap:]. Heap instVarNames
ApiToolExpression: Heap instVarNames
ApiToolExpression: Heap >> #add: sourceCode
ApiToolExpression: (Heap >> #add:) sourceCode
ApiToolExpression: (Heap >> #reSort) sourceCode
ApiToolExpression: Heap new instVarNamed: #indexUpdateBlock

Cheers I am at the moment experimenting with getting an AI to write test methods for me. The current results are a mixture of simple and advanced :-) To get started I wanted to write tests for a class that does not go to the web, file or UI, and doing something which is standard, but with no method comments. So the experiments is for the class "Heap". I have not really been successful, but now I have what I see as a breakthrough, and wanted to know if anyone else had the same experience? -- Kasper Here is an example Heap >> upHeap: anIndex "Check the heap upwards for correctness starting at anIndex. Everything below anIndex is ok." | value k kDiv2 tmp | anIndex = 0 ifTrue:[^self]. k := anIndex. value := array at: anIndex. [ (k > 1) and:[self sorts: value before: (tmp := array at: (kDiv2 := k bitShift: -1))] ] whileTrue:[ array at: k put: tmp. self updateObjectIndex: k. k := kDiv2]. array at: k put: value. self updateObjectIndex: k And the test build by AI is this: testUpHeap | arr | "Test upHeap: for index 0, should do nothing" refHeap upHeap: 0. self assert: true. "No error, no change expected" "Set up min-heap sort block" refHeap sortBlock: [ :a :b | a <= b ]. "Test upHeap:1 on single element, no change" arr := Array new: 10. arr at: 1 put: 5. refHeap instVarAt: 1 put: arr. refHeap instVarAt: 2 put: 1. refHeap upHeap: 1. self assert: ((refHeap instVarAt: 1) at: 1) equals: 5. "Test upHeap:2 with swap needed (smaller child)" arr := Array new: 10. arr at: 1 put: 3. arr at: 2 put: 1. refHeap instVarAt: 1 put: arr. refHeap instVarAt: 2 put: 2. refHeap upHeap: 2. self assert: ((refHeap instVarAt: 1) at: 1) equals: 1. self assert: ((refHeap instVarAt: 1) at: 2) equals: 3. "Test upHeap:2 with no swap (larger child)" arr := Array new: 10. arr at: 1 put: 3. arr at: 2 put: 4. refHeap instVarAt: 1 put: arr. refHeap instVarAt: 2 put: 2. refHeap upHeap: 2. self assert: ((refHeap instVarAt: 1) at: 1) equals: 3. self assert: ((refHeap instVarAt: 1) at: 2) equals: 4. "Test upHeap:3 with one swap to root" arr := Array new: 10. arr at: 1 put: 3. arr at: 2 put: 4. arr at: 3 put: 2. refHeap instVarAt: 1 put: arr. refHeap instVarAt: 2 put: 3. refHeap upHeap: 3. self assert: ((refHeap instVarAt: 1) at: 1) equals: 2. self assert: ((refHeap instVarAt: 1) at: 2) equals: 4. self assert: ((refHeap instVarAt: 1) at: 3 )equals: 3. "Test upHeap:4 with multiple swaps" arr := Array new: 10. arr at: 1 put: 1. arr at: 2 put: 3. arr at: 3 put: 2. arr at: 4 put: 0. refHeap instVarAt: 1 put: arr. refHeap instVarAt: 2 put: 4. refHeap upHeap: 4. self assert: ((refHeap instVarAt: 1) at: 1) equals: 0. self assert: ((refHeap instVarAt: 1) at: 2) equals: 1. self assert: ((refHeap instVarAt: 1) at: 3) equals: 2. self assert: ((refHeap instVarAt: 1) at: 4 )equals: 3. And the input to make it doit is AIATest04 new build: Heap >> #upHeap:: I have added a tool call that allows Grok to call and execute Pharo code, so to produce the test, it has executed these calls: ApiToolExpression: Heap compileAllFrom: 'Collections-Sequenceable'. Heap methods select: [:m | m selector = #upHeap:]. Heap instVarNames ApiToolExpression: Heap instVarNames ApiToolExpression: Heap >> #add: sourceCode ApiToolExpression: (Heap >> #add:) sourceCode ApiToolExpression: (Heap >> #reSort) sourceCode ApiToolExpression: Heap new instVarNamed: #indexUpdateBlock