2012년 12월 13일 목요일

[OSX] 숨긴 폴더 및 파일 표시

터미널을 통해 다음 명령어를 실행한다.
defaults write com.apple.Finder AppleShowAllFiles YES

Finder 강제 종료 후 재실행이 필요하다.

[iOS] Volume Purchasing for Business Program


 어제, 미국에 한해 iOS 앱을 카피 단위로 판매할 수 있는 Volume Purchasing for Business Program(VPP)이 새로 발표됐다. 볼륨 앱 스토어를 통해 2~1000 Copy 단위(Volume)로 앱을 판매/구매할 수 있으며, 구매한 앱은 리딤 코드를 사용하여 앱스토어를 거치지 않고 자체적으로 배포가 가능하다. 아직은 미국 기업에 한정되어 있지만, 곧 한국에도 적용이 될 것이라 생각한다. 개인적인 차원에서도, 신규 사업분야 진출의 일환으로 모바일 사업을 준비 중인 팀 차원에서도 여러모로 큰 도움이 될 것 같다.

* 2013년 1월 현재, 미국 뿐 아니라 호주, 캐나다, 프랑스 등 10개 국가로 확대되었습니다.

[iOS] 루트 뷰 컨트롤러 표시하기

popToRootViewControllerAnimated: 메시지를 이용하면 루트 컨트롤러를 바로 표시할 수 있다.
[self.navigationController popToRootViewControllerAnimated:YES];


미리 알았다면 이런 짓은 안했을텐데.
for (int i = 0; i < [self.navigationController.viewControllers count]; i++) {
     [self.navigationController popViewControllerAnimated:NO];
}

[ASP.NET MVC] IValidatableObject 개체 테스트하기

IValidatableObject 인터페이스를 이용하여 유효성 검사를 수행하는 객체는 Validator 클래스를 통해 테스트할 수 있다. 다음은 테스트 주도 ASP.NET MVC 프로그래밍 책의 예제를 개선한 코드들이다. 참고로 책의 예제에서는 유효성 검사를 위해 커스텀 인터페이스를 사용하고 있다.

public class Todo : IValidatableObject
{
    //[Required]
    //[StringLength(25)]
    public string Title { get; set; }

    public IEnumerable<ValidationResult> Validate(
        ValidationContext validationContext)
    {
        if (string.IsNullOrEmpty(Title))
            yield return new ValidationResult(
                "제목이 입력되지 않았습니다.", 
                new[] { "Title" });

        if (Title != null && Title.Length > 25)
            yield return new ValidationResult(
                "제목이 25자를 초과할 수 없습니다.", 
                new[] { "Title" });
    }
}


제목 길이에 따른 각 개체들의 유효성 검사는 다음과 같이 테스트 한다.
[TestFixture]
public class TodoTest
{
    [Test]
    public void Title_Length_Should_Be_To_Maximum_Of_25_Characters()
    {
        // Arrange
        Todo longTodo = new Todo { Title = "123456789ABCDEF123456789ABCDEF" };
        Todo twentyFiveCharacterTodo = new Todo { Title = "123456789ABCDEF1234567" };
        Todo shortTodo = new Todo { Title = "123456789" };

        // Assert
        Assert.IsFalse(IsValid(longTodo));
        Assert.IsTrue(IsValid(twentyFiveCharacterTodo));
        Assert.IsTrue(IsValid(shortTodo));
    }

    private bool IsValid(IValidatableObject toValidate)
    {
        return Validator.TryValidateObject(
            toValidate, 
            new ValidationContext(toValidate, null, null), 
            null, 
            true);
    }
}


에러 메시지를 확인하고 싶다면 ValidationResult 리스트를 사용하면 된다.
[Test]
public void Title_Length_Should_Be_To_Maximum_Of_25_Characters()
{
    // Arrange
    Todo longTodo = new Todo { Title = "123456789ABCDEF123456789ABCDEF" };

    var result = new List<ValidationResult>();

    Validator.TryValidateObject(
        longTodo,
        new ValidationContext(longTodo, null, null),
        result,
        true);
        
    // Assert
    Assert.AreEqual(1, result.Count);
    Assert.AreEqual("제목은 25자를 초과할 수 없습니다.", result[0].ErrorMessage);
}

2012년 12월 12일 수요일

[ASP.NET MVC] ASP.NET MVC4 테스트 프로젝트에서 MVCContrib 사용 시 예외 발생 해결

ASP.NET MVC4  + MVCContrib 프레임워크를 사용하는 프로젝트들을 테스트하면 MVCContrib의 몇 몇 확장 메서드들이(ShouldMapTo<T>(), AssertActionRedirect<T>()와 같은) 이상한 예외들을 발생시킨다. 동일한 두 개의 타입을 틀린 타입으로 취급한다.

MvcContrib.TestHelper.ActionResultAssertionException : Expected result to be of type RedirectToRouteResult. It is actually of type RedirectToRouteResult.

MVCContrib3에서 참조되는 System.Web.Mvc.dll의 버전(1.0 ~ 3.0)이 테스트 프로젝트에서 참조된 버전(4.0)과 다르기 때문에 발생하는 문제다. App.config를 통해 1.0 ~ 3.0 버전을 강제로 4.0으로 바인딩하여 해결한다. 테스트 클래스 프로젝트에 App.config를 추가하고 다음과 같이 입력해준다.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
                <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="4.0.0.0" />
            </dependentAssembly>
        </assemblyBinding>
    </runtime>    
</configuration>