C# ArraySegment<T>와 테스트

2018-06-19

들어가며

WzComparerR2는 C#을 사용한다. 내가 만든 기능 중에서 특정 장비의 경로를 찾아가기 위해 StringLinker에서의 경로를 찾아 이를 활용하는 부분이 있는데, 여기서 split한 문자열의 가운데만 join 할 필요가 있었다. 그래서 이전에는 List를 하나 새로 만들어서 LINQ의 GetRange()를 하고 다시 List로 만드는 형태의 복잡한 작업을 하고 있었다. 그래서 이를 KENNYSOFT/WzcomparerR2@bee5a3a에서 ArraySegment<string>으로 바꾼 적이 있다.#

이 이야기를 왜 하느냐 하면 문제가 생겼기 때문이다. 그런데 그냥 단순한 문제는 아니다. 이제부터 이 사건의 경위를 설명하려고 한다.

WzComparerR2를 작업하면서 여러 프로젝트의 .NET 프레임워크 버전이 달라서, 그냥 좋은 게 좋은 거지 하고 무작정 최신 버전을 다 때려 박았던 적이 있다. KENNYSOFT/WzComparerR2@1baff46KENNYSOFT/WzComparerR2@5910c2d이다. 그런데 이 프레임워크 버전은 계속 4.7, 4.7.1, 4.7.2 이런 식으로 빠르게 올라가서 굳이 따라잡는 걸 포기하고 다시 원 프로젝트에서 하던 대로 맞춰 예전 버전으로 돌아간 이력이 있다. 이게 KENNYSOFT/WzComparerR2@31521c9이다.

그렇다. bee5a3a 커밋이 .NET 프레임워크 버전을 올렸다가 내린 사이에 이루어진 것이다. 그렇기에 내가 예상치 못한 문제가 발생하고 있었고, 이건 현재 배포된 KMS-v2.1.0에서도 마찬가지였다. 그런데 아무도 리포팅해주지 않은 것으로 보아, 아무도 이 기능을 사용하지 않고 있었던 것 같다. 아래에서 생긴 문제를 더 자세하게 설명한다.

문제 상황

먼저 다음 글을 보자: c# - what is the use of ArraySegment<T> class? - Stack Overflow

중요한 부분은 다음과 같다.

ArraySegment<T> has become a lot more useful in .NET 4.5 as it now implements:

as opposed to the .NET 4 version which implemented no interfaces whatsoever.

중요한 부분이 뭔지 모르겠다고? 다시 한번 보자.

as opposed to the .NET 4 version which implemented no interfaces whatsoever.

WzComparerR2 프로젝트는 .NET 4.5 이상으로 올라갔다가 롤백 때 다시 .NET 3.5로 되돌아왔다. 그리고 .NET 3.5 환경에서는 해당 추가된 코드가 테스트 되어 본 적이 없기 때문에 문제가 발생하게 되었다. 실제 MSDN 문서와 여기서 정의된 모습을 보자.

ArraySegment(T) Structure (System) (.NET Framework 4.0)

[SerializableAttribute]
public struct ArraySegment<T>

ArraySegment(T) Structure (System) (.NET Framework 4.5)

[SerializableAttribute]
public struct ArraySegment<T> : IList<T>, ICollection<T>, IEnumerable<T>, 
    IEnumerable, IReadOnlyList<T>, IReadOnlyCollection<T>

implement 하는 요소가 있고 없고의 차이가 크다. 이에 따라 LINQ 등의 기능을 사용할 수 있고 없고도 달라진다.

그래서 실제로 생긴 문제는 장비의 아이콘이 나오지 않는다는 것이었다. 아래 그림과 같다.

CashPackageRender 버그
그림 1 CashPackageRender 버그

사실 이곳에서 찾은 버그는 아니고, 다른 기능을 구현하다가 왜 내보내기가 안 되는지 한참을 찾다가 발견했다. 접근하는 경로를 메시지로 출력해보고 나서야 왜 그랬는지 알 수 있었다. 아래 같은 경로를 접근하고 있었다.

기본 ToString 메소드가 호출된 모습
그림 2 기본 ToString 메소드가 호출된 모습

테스트의 중요성

테스트는 정말 중요하다. 유닛 테스트, 테스트 주도 개발 등의 방법론이 괜히 나온 것이 아닐 테다. 나도 최대한 많은 테스트를 진행하고 있기는 하다만, 그거야 어차피 내가 추가한 코드 사이에서이겠지 라고 생각하고 넘긴 점이 없지 않아 있었을 것이다. 이처럼 SDK 변경 등의 이유로, 그것도 특히 버전을 내리는 것으로 인해 사용하는 요소의 특성이 달라지는 상황도 반드시 확인해보아야 할 것이다.

돌아가기


댓글