274 lines
15 KiB
C#
274 lines
15 KiB
C#
using System.Collections.Generic;
|
|
using AGVNavigationCore.Models;
|
|
|
|
namespace AGVPathTester
|
|
{
|
|
/// <summary>
|
|
/// AGV 경로 탐색 테스트 케이스 정의
|
|
/// </summary>
|
|
public static class TestCases
|
|
{
|
|
/// <summary>
|
|
/// 기본 경로 탐색 테스트 케이스
|
|
/// </summary>
|
|
public class BasicPathTestCase
|
|
{
|
|
public string StartNodeId { get; set; }
|
|
public string TargetNodeId { get; set; }
|
|
public AgvDirection CurrentDirection { get; set; }
|
|
public string Description { get; set; }
|
|
public bool ExpectedSuccess { get; set; }
|
|
|
|
public BasicPathTestCase(string startNodeId, string targetNodeId, AgvDirection currentDirection, string description, bool expectedSuccess = true)
|
|
{
|
|
StartNodeId = startNodeId;
|
|
TargetNodeId = targetNodeId;
|
|
CurrentDirection = currentDirection;
|
|
Description = description;
|
|
ExpectedSuccess = expectedSuccess;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 방향 전환 테스트 케이스
|
|
/// </summary>
|
|
public class DirectionChangeTestCase
|
|
{
|
|
public string StartNodeId { get; set; }
|
|
public string TargetNodeId { get; set; }
|
|
public AgvDirection CurrentDirection { get; set; }
|
|
public AgvDirection RequiredDirection { get; set; }
|
|
public string Description { get; set; }
|
|
public bool ExpectedSuccess { get; set; }
|
|
public List<string> ExpectedPath { get; set; }
|
|
|
|
public DirectionChangeTestCase(string startNodeId, string targetNodeId, AgvDirection currentDirection, AgvDirection requiredDirection, string description, bool expectedSuccess = true, List<string> expectedPath = null)
|
|
{
|
|
StartNodeId = startNodeId;
|
|
TargetNodeId = targetNodeId;
|
|
CurrentDirection = currentDirection;
|
|
RequiredDirection = requiredDirection;
|
|
Description = description;
|
|
ExpectedSuccess = expectedSuccess;
|
|
ExpectedPath = expectedPath ?? new List<string>();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이동 기반 테스트 케이스 (이전 위치 → 현재 위치 → 목표 위치)
|
|
/// </summary>
|
|
public class MovementBasedTestCase
|
|
{
|
|
public string PreviousRfid { get; set; }
|
|
public string CurrentRfid { get; set; }
|
|
public string TargetRfid { get; set; }
|
|
public AgvDirection ExpectedDirection { get; set; }
|
|
public string Description { get; set; }
|
|
public bool ExpectedSuccess { get; set; }
|
|
public List<string> ExpectedRfidPath { get; set; }
|
|
|
|
public MovementBasedTestCase(string previousRfid, string currentRfid, string targetRfid, AgvDirection expectedDirection, string description, bool expectedSuccess = true, List<string> expectedRfidPath = null)
|
|
{
|
|
PreviousRfid = previousRfid;
|
|
CurrentRfid = currentRfid;
|
|
TargetRfid = targetRfid;
|
|
ExpectedDirection = expectedDirection;
|
|
Description = description;
|
|
ExpectedSuccess = expectedSuccess;
|
|
ExpectedRfidPath = expectedRfidPath ?? new List<string>();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 기본 경로 탐색 테스트 케이스 목록 (RFID 기반으로 수정)
|
|
/// RFID 매핑: 001→N001, 005→N011, 037→N015, 041→존재하지않음
|
|
/// </summary>
|
|
public static List<BasicPathTestCase> GetBasicPathTestCases()
|
|
{
|
|
return new List<BasicPathTestCase>
|
|
{
|
|
// 단순 직선 경로
|
|
new BasicPathTestCase("N001", "N002", AgvDirection.Forward, "단순 인접 노드 이동"),
|
|
new BasicPathTestCase("N001", "N003", AgvDirection.Forward, "단거리 직선 경로"),
|
|
|
|
// 중거리 경로
|
|
new BasicPathTestCase("N001", "N010", AgvDirection.Forward, "중거리 경로 탐색"),
|
|
new BasicPathTestCase("N011", "N019", AgvDirection.Backward, "RFID 005→015: 후진 상태에서 중거리 이동"),
|
|
|
|
// 갈림길을 포함한 경로
|
|
new BasicPathTestCase("N001", "N020", AgvDirection.Forward, "갈림길 포함 경로"),
|
|
new BasicPathTestCase("N010", "N030", AgvDirection.Forward, "복잡한 갈림길 경로"),
|
|
|
|
// RFID 기반 실제 경로 (PATHSCENARIO.md 기반) - 올바른 NodeID 매핑 사용
|
|
new BasicPathTestCase("N013", "N019", AgvDirection.Forward, "RFID 007→015: 직진 경로"),
|
|
new BasicPathTestCase("N013", "N026", AgvDirection.Forward, "RFID 007→019: 충전기 경로"),
|
|
new BasicPathTestCase("N013", "N001", AgvDirection.Forward, "RFID 007→001: 장비 경로"),
|
|
|
|
// 갈림길 테스트 (RFID 005는 N011 갈림길)
|
|
new BasicPathTestCase("N004", "N019", AgvDirection.Forward, "RFID 004→015: N011 갈림길 통과"),
|
|
new BasicPathTestCase("N012", "N023", AgvDirection.Backward, "RFID 012→016: 갈림길 역방향"),
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 방향 전환 테스트 케이스 목록 (PATHSCENARIO.md RFID 기반)
|
|
/// RFID → NodeID 매핑: 005→N011, 037→N028, 007→N013, 015→N019, 001→N001, 004→N004
|
|
/// </summary>
|
|
public static List<DirectionChangeTestCase> GetDirectionChangeTestCases()
|
|
{
|
|
return new List<DirectionChangeTestCase>
|
|
{
|
|
// PATHSCENARIO.md Case 1: AGV가 전진방향으로 008→007 이동 후
|
|
// Q1: 007→015 (충전기, 전진 도킹) - 방향전환 불필요
|
|
new DirectionChangeTestCase("N013", "N019", AgvDirection.Forward, AgvDirection.Forward,
|
|
"Q1: RFID 007→015 (충전기, 전진 도킹) - 방향전환 불필요",
|
|
true, new List<string> { "N013", "N012", "N011", "N004", "N022", "N023", "N024", "N019" }),
|
|
|
|
// Q2: 007→019 (충전기, 전진 도킹) - 방향전환 불필요
|
|
new DirectionChangeTestCase("N013", "N026", AgvDirection.Forward, AgvDirection.Forward,
|
|
"Q2: RFID 007→019 (충전기, 전진 도킹) - 방향전환 불필요",
|
|
true, new List<string> { "N013", "N012", "N011", "N004", "N022", "N023", "N024", "N025", "N026" }),
|
|
|
|
// Q3: 007→001 (장비, 후진 도킹) - 005 갈림길에서 037 우회
|
|
new DirectionChangeTestCase("N013", "N001", AgvDirection.Forward, AgvDirection.Backward,
|
|
"Q3: RFID 007→001 (장비, 후진 도킹) - 005 갈림길에서 037 우회",
|
|
true, new List<string> { "N013", "N012", "N011", "N028", "N011", "N004", "N003", "N002", "N001" }),
|
|
|
|
// Q4: 007→011 (장비, 후진 도킹) - 005 갈림길에서 037 우회
|
|
// RFID 011 → N010
|
|
new DirectionChangeTestCase("N013", "N010", AgvDirection.Forward, AgvDirection.Backward,
|
|
"Q4: RFID 007→011 (장비, 후진 도킹) - 005 갈림길에서 037 우회",
|
|
true, new List<string> { "N013", "N012", "N011", "N028", "N011", "N004", "N031", "N008", "N009", "N010" }),
|
|
|
|
// Case 2: AGV가 후진방향으로 008→007 이동 후
|
|
// Q7: 007→015 (충전기, 전진 도킹) - 005에서 037 우회 후 전환
|
|
new DirectionChangeTestCase("N013", "N019", AgvDirection.Backward, AgvDirection.Forward,
|
|
"Q7: RFID 007→015 (충전기, 전진 도킹) - 005에서 037 우회 후 전환",
|
|
true, new List<string> { "N013", "N012", "N011", "N028", "N011", "N004", "N022", "N023", "N024", "N019" }),
|
|
|
|
// 실제 맵 기반 간단한 테스트들
|
|
// N004 갈림길 활용 (N003, N022, N031 연결)
|
|
new DirectionChangeTestCase("N003", "N022", AgvDirection.Forward, AgvDirection.Backward,
|
|
"N004 갈림길: N003→N022 (전진→후진 전환)",
|
|
true, new List<string> { "N003", "N004", "N022" }),
|
|
|
|
new DirectionChangeTestCase("N003", "N031", AgvDirection.Forward, AgvDirection.Backward,
|
|
"N004 갈림길: N003→N031 (전진→후진 전환)",
|
|
true, new List<string> { "N003", "N004", "N031" }),
|
|
|
|
// N011 갈림길 활용 (N012, N004, N015 연결) - RFID 005는 N011
|
|
new DirectionChangeTestCase("N012", "N019", AgvDirection.Forward, AgvDirection.Backward,
|
|
"N011 갈림길 (RFID 005): N012→N019 (전진→후진 전환)",
|
|
true, new List<string> { "N012", "N011", "N004", "N022", "N023", "N024", "N019" }),
|
|
|
|
// 방향 전환이 필요 없는 경우 (같은 방향)
|
|
new DirectionChangeTestCase("N013", "N019", AgvDirection.Forward, AgvDirection.Forward,
|
|
"방향 전환 불필요: RFID 007→015 (전진→전진)",
|
|
true, new List<string> { "N013", "N012", "N011", "N004", "N022", "N023", "N024", "N019" }),
|
|
|
|
new DirectionChangeTestCase("N012", "N019", AgvDirection.Backward, AgvDirection.Backward,
|
|
"방향 전환 불필요: N012→N019 (후진→후진)",
|
|
true, new List<string> { "N012", "N011", "N004", "N022", "N023", "N024", "N019" })
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 특정 문제 시나리오 테스트 케이스 (디버깅용)
|
|
/// </summary>
|
|
public static List<DirectionChangeTestCase> GetProblematicTestCases()
|
|
{
|
|
return new List<DirectionChangeTestCase>
|
|
{
|
|
// 사용자가 직접 보고한 문제들 (RFID 매핑 적용)
|
|
new DirectionChangeTestCase("N004", "N015", AgvDirection.Forward, AgvDirection.Backward,
|
|
"🚨 사용자 보고: RFID 004→037(N015) 되돌아가기 발생"),
|
|
new DirectionChangeTestCase("N012", "N015", AgvDirection.Backward, AgvDirection.Backward,
|
|
"🚨 사용자 보고: RFID 012→037(N015) 비효율적 경로"),
|
|
new DirectionChangeTestCase("N012", "N023", AgvDirection.Backward, AgvDirection.Forward,
|
|
"🚨 사용자 보고: RFID 012→016(N023) 되돌아가기 발생"),
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 스트레스 테스트용 대량 케이스 생성
|
|
/// </summary>
|
|
public static List<BasicPathTestCase> GenerateStressTestCases(List<string> allNodeIds, int count = 50)
|
|
{
|
|
var testCases = new List<BasicPathTestCase>();
|
|
var random = new System.Random(42); // 고정 시드로 재현 가능한 테스트
|
|
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
var startNodeId = allNodeIds[random.Next(allNodeIds.Count)];
|
|
var targetNodeId = allNodeIds[random.Next(allNodeIds.Count)];
|
|
var direction = random.Next(2) == 0 ? AgvDirection.Forward : AgvDirection.Backward;
|
|
|
|
if (startNodeId != targetNodeId)
|
|
{
|
|
testCases.Add(new BasicPathTestCase(
|
|
startNodeId,
|
|
targetNodeId,
|
|
direction,
|
|
$"스트레스 테스트 #{i + 1}"
|
|
));
|
|
}
|
|
}
|
|
|
|
return testCases;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이동 기반 테스트 케이스 목록 (실제 AGV 이동 시나리오)
|
|
/// </summary>
|
|
public static List<MovementBasedTestCase> GetMovementBasedTestCases()
|
|
{
|
|
return new List<MovementBasedTestCase>
|
|
{
|
|
// 핵심 시나리오: 033→032 후진 이동 중인 AGV가 001로 가는 경우
|
|
new MovementBasedTestCase("033", "032", "001", AgvDirection.Backward,
|
|
"🎯 핵심 시나리오: RFID 033→032 후진 이동 AGV가 001(장비) 목적지",
|
|
true, new List<string> { "032", "031", "030", "...", "001" }),
|
|
|
|
// 다양한 이동 패턴 테스트
|
|
new MovementBasedTestCase("001", "002", "015", AgvDirection.Forward,
|
|
"RFID 001→002 전진 이동 AGV가 015(충전기) 목적지",
|
|
true, new List<string> { "002", "003", "004", "012", "013", "014", "015" }),
|
|
|
|
new MovementBasedTestCase("015", "014", "001", AgvDirection.Backward,
|
|
"RFID 015→014 후진 이동 AGV가 001(장비) 목적지",
|
|
true, new List<string> { "014", "013", "012", "004", "003", "002", "001" }),
|
|
|
|
new MovementBasedTestCase("004", "005", "019", AgvDirection.Forward,
|
|
"RFID 004→005 전진 이동(갈림길 진입) AGV가 019(충전기) 목적지",
|
|
true, new List<string> { "005", "037", "036", "035", "034", "018", "019" }),
|
|
|
|
new MovementBasedTestCase("005", "004", "037", AgvDirection.Backward,
|
|
"RFID 005→004 후진 이동(갈림길 이탈) AGV가 037 목적지",
|
|
true, new List<string> { "004", "005", "037" }),
|
|
|
|
// 🚨 AGV 물리적 제약사항 테스트: 갈림길 즉시 방향전환 금지
|
|
new MovementBasedTestCase("018", "019", "015", AgvDirection.Forward,
|
|
"🚨 물리적 제약: RFID 018→019 전진 이동 AGV가 015(충전기) 목적지 - 012 갈림길 즉시 방향전환 금지",
|
|
true, new List<string> { "019", "018", "017", "016", "012", "004", "012", "013", "014", "015" }),
|
|
|
|
new MovementBasedTestCase("016", "012", "013", AgvDirection.Backward,
|
|
"🚨 물리적 제약: RFID 016→012 후진 이동 AGV가 013 목적지 - 012에서 즉시 013 전진 금지",
|
|
true, new List<string> { "012", "004", "012", "013" }),
|
|
|
|
// 🔥 핵심 시나리오: AGV 물리적 방향과 갈림길 방향전환
|
|
new MovementBasedTestCase("032", "031", "008", AgvDirection.Backward,
|
|
"🔥 핵심 시나리오: RFID 032→031 후진 이동 AGV가 008 목적지 - 031→005(전진)→004(좌회전)→008(후진)",
|
|
true, new List<string> { "031", "032", "033", "034", "035", "036", "037", "005", "004", "012", "006", "007", "008" }),
|
|
|
|
// 방향 전환이 필요한 시나리오
|
|
new MovementBasedTestCase("032", "033", "001", AgvDirection.Forward,
|
|
"RFID 032→033 전진 이동 AGV가 001(후진 도킹) 목적지 - 방향 전환 필요",
|
|
true, new List<string> { "033", "034", "018", "017", "016", "037", "005", "004", "003", "002", "001" }),
|
|
|
|
new MovementBasedTestCase("007", "006", "015", AgvDirection.Backward,
|
|
"RFID 007→006 후진 이동 AGV가 015(전진 도킹) 목적지 - 방향 전환 필요",
|
|
true, new List<string> { "006", "005", "037", "005", "004", "012", "013", "014", "015" }),
|
|
};
|
|
}
|
|
}
|
|
} |