Here are some examples for group_by/4 from library(solution_sequences) as test cases.
:- begin_tests(group_by).
% run_tests(group_by).
data(c1, a2, b3).
data(a1, c2, c3).
data(b1, b2, a3).
data(a1, a2, a3).
data(a1, c2, d3).
data(b1, a2, a3).
data(b1, b2, b3).
data(c1, a2, a3).
data(a1, c2, a3).
data(c1, b2, a3).
data(a1, b2, b3).
data(b1, a2, b3).
data(a1, c2, b3).
data(c1, b2, b3).
data(a1, b2, a3).
data(d1, a1, a1).
% Converts the data/3 facts to a list
data_fact_to_list(List) :-
bagof(data(A,B,C),data(A,B,C),List).
% Group by: single value
% Data source: facts
test(1, all(A-Bag == [a1-[c2,a2,c2,c2,b2,c2,b2],b1-[b2,a2,b2,a2],c1-[a2,a2,b2,b2],d1-[a1]] ) ) :-
group_by(A, B, data(A,B,_), Bag).
% Group by: single value
% Item output format: Compound with functor (,)
% Data source: facts
test(2, all(A-Bag == [a1-[(c2,c3),(a2,a3),(c2,d3),(c2,a3),(b2,b3),(c2,b3),(b2,a3)],b1-[(b2,a3),(a2,a3),(b2,b3),(a2,b3)],c1-[(a2,b3),(a2,a3),(b2,a3),(b2,b3)],d1-[(a1,a1)]] ) ) :-
group_by(A, (B,C), data(A,B,C), Bag).
% Group by: multiple values
% Data source: facts
test(3, all((A,B)-Bag == [(a1,a2)-[a3],(a1,b2)-[b3,a3],(a1,c2)-[c3,d3,a3,b3],(b1,a2)-[a3,b3],(b1,b2)-[a3,b3],(c1,a2)-[b3,a3],(c1,b2)-[a3,b3],(d1,a1)-[a1]] ) ) :-
group_by((A,B), C, data(A,B,C), Bag).
% NB Uses =@= (structural equivalence) instead of == (comparison) to allow for variables in list.
% Group by: multiple values
% Data source: facts
test(4, all((A,B,C)-Bag =@= [(a1,a2,a3)-[_],(a1,b2,a3)-[_],(a1,b2,b3)-[_],(a1,c2,a3)-[_],(a1,c2,b3)-[_],(a1,c2,c3)-[_],(a1,c2,d3)-[_],(b1,a2,a3)-[_],(b1,a2,b3)-[_],(b1,b2,a3)-[_],(b1,b2,b3)-[_],(c1,a2,a3)-[_],(c1,a2,b3)-[_],(c1,b2,a3)-[_],(c1,b2,b3)-[_],(d1,a1,a1)-[_]] ) ) :-
group_by((A,B,C), _, data(A,B,C), Bag).
% Item output format: Compound with functor (,)
% Group by: single value
% Data source: List
test(5, all(A-Bag == [a1-[(c2,c3),(a2,a3),(c2,d3),(c2,a3),(b2,b3),(c2,b3),(b2,a3)],b1-[(b2,a3),(a2,a3),(b2,b3),(a2,b3)],c1-[(a2,b3),(a2,a3),(b2,a3),(b2,b3)],d1-[(a1,a1)]] ) ) :-
data_fact_to_list(List),
group_by(A, (B,C), member(data(A,B,C),List), Bag).
% Group by: single value
% Item output format: structure item(B,C)
% Data source: facts
test(6, all(A-Bag == [a1-[item(c2,c3),item(a2,a3),item(c2,d3),item(c2,a3),item(b2,b3),item(c2,b3),item(b2,a3)],b1-[item(b2,a3),item(a2,a3),item(b2,b3),item(a2,b3)],c1-[item(a2,b3),item(a2,a3),item(b2,a3),item(b2,b3)],d1-[item(a1,a1)]] ) ) :-
group_by(A, item(B,C), data(A,B,C), Bag).
:- end_tests(group_by).
Example run
?- run_tests(group_by).
% PL-Unit: group_by ...... done
% All 6 tests passed
true.