ラベル Visual Studio の投稿を表示しています。 すべての投稿を表示
ラベル Visual Studio の投稿を表示しています。 すべての投稿を表示

2015年5月16日

Assert.AreEqual に NaN が入るとテストが成功するバグ (VS2010~2012)

Visual Studio 2010 (たぶん 2012 も) の MSTest の delta を指定する Assert.AreEqual には下記のようなバグがある。

// delta を指定する場合
Assert.AreEqual(1.0, double.NaN, 1.0); // 成功

// delta を指定しない場合
Assert.AreEqual(1.0, double.NaN); // 失敗

// 失敗するのが正しい動作なので、delta を指定する方はバグっている

バグの原因はソースを見れば明らかで、NaN を考慮していないため。
[Assert.AreEqual のソース (ILSpy)]

public static void AreEqual(double expected, double actual, double delta, string message, params object[] parameters)
{
    if (Math.Abs(expected - actual) > delta)
    {
        string message2 = FrameworkMessages.AreEqualDeltaFailMsg((message == null) ? string.Empty : Assert.ReplaceNulls(message), expected.ToString(CultureInfo.CurrentCulture.NumberFormat), actual.ToString(CultureInfo.CurrentCulture.NumberFormat), delta.ToString(CultureInfo.CurrentCulture.NumberFormat));
        Assert.HandleFail("Assert.AreEqual", message2, parameters);
    }
}

// 比較条件に NaN が含まれると false になるので if の中に入らない

Assert.AreEqual が含まれるアセンブリの配置場所は
%VS のディレクトリ%\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll

Visual Studio 2013 では修正されているが・・・

このバグは VS2013 では修正されている。
[修正済み Assert.AreEqual のソース (ILSpy)]

public static void AreEqual(double expected, double actual, double delta, string message, params object[] parameters)
{
    if (double.IsNaN(expected) || double.IsNaN(actual) || double.IsNaN(delta))
    {
        string message2 = FrameworkMessages.AreEqualDeltaFailMsg((message == null) ? string.Empty : Assert.ReplaceNulls(message), expected.ToString(CultureInfo.CurrentCulture.NumberFormat), actual.ToString(CultureInfo.CurrentCulture.NumberFormat), delta.ToString(CultureInfo.CurrentCulture.NumberFormat));
         Assert.HandleFail("Assert.AreEqual", message2, parameters);
    }
    if (Math.Abs(expected - actual) > delta)
    {
        string message3 = FrameworkMessages.AreEqualDeltaFailMsg((message == null) ? string.Empty : Assert.ReplaceNulls(message), expected.ToString(CultureInfo.CurrentCulture.NumberFormat), actual.ToString(CultureInfo.CurrentCulture.NumberFormat), delta.ToString(CultureInfo.CurrentCulture.NumberFormat));
        Assert.HandleFail("Assert.AreEqual", message3, parameters);
    }
}

// 引数のいずれかが NaN の場合、テスト失敗

が、VS2010 をインストールしている場合、修正されたアセンブリ「Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll」(以降、UnitTestFramework.dll)が使われないケースがある。
[確認できた発生条件]
  • VS2010 と VS2013 インストール済 (インストール順序は関係ない)
  • .NET 4.0 以上のテストプロジェクト

原因

VS2010 は GAC に .NET 2.0 と 4.0 の UnitTestFramework.dll (バグ有り) をインストールするが、VS2013 は .NET 2.0 の UnitTestFramework.dll (修正済み) しかインストールしないため。
かつ、VS2010 の UnitTestFramework.dll (.NET 4.0) と VS2013 の UnitTestFramework.dll (.NET 2.0) のバージョン番号「10.0.0.0」が同じであるため。(公開キーは MS 製品なので同じ)
※他にバージョン番号「10.1.0.0」の UnitTestFramework.dll も存在するが、設定で参照されないようになっている

VS2010 と VS2013 をインストールした環境の GAC は下記の状態になる。
CLR 2.0 %windir%\assembly 修正済み
CLR 4 %windir%\Microsoft.NET\assembly バグ有り

そして、CLR 4 の実行アプリは CLR 4 の GAC を優先するため、バグ有りの方の UnitTestFramework.dll が参照されることになる。(参考:GAC 内のアセンブリ検索方法
公開キーが一緒なのは仕方ないとして、バージョン番号さえ変えとけば、こんな事態は回避できた・・・

解決手段

上記リンクでも説明されてるけど、CLR 4 の GAC の実ファイルを移動または削除すればOK。
%windir%\Microsoft.NET\assembly\GAC_MSIL\Microsoft.VisualStudio.QualityTools.UnitTestFramework\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll

副次的な効果として、VS2010 のテストプロジェクトからも修正された UnitTestFramework.dll が使用されるようになる。

2014年9月24日

NuGet のリポジトリパスの変更

NuGet のリポジトリパス(パッケージがダウンロードされる場所)は、デフォルトだと次である。
$(ソリューションディレクトリ)\packages\

ソリューション 1 つだとデフォルトのままでも問題ないのだが、複数だとソリューション毎にリポジトリパスが存在し、それぞれパッケージがダウンロードされることになる。

・・・同じパッケージが違うディレクトリにダウンロードされるのって微妙じゃね?
ということが考慮されてかは分からないが、リポジトリパスは nuget.config を書くことで任意のパスを指定できる。

[リポジトリパス指定用の nuget.config 記述例]

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <config>
    <add key="repositoryPath" value="リポジトリパス(絶対or相対パス)" />
  </config>
</configuration>

ちなみに nuget.config の配置場所。
ソリューション毎 $(ソリューションディレクトリ)\nuget.config
共通(ユーザー毎) %APPDATA%\NuGet\NuGet.Config

nuget.config の他の設定項目。

2014年4月25日

Visual Studio の CSS の警告がうざい場合の対処法

Visual Studio 2010 の場合、真っ当な対処法として、Web Standards Update for Microsoft Visual Studio 2010 SP1 をインストールし、css ファイルを開いた際のツールバーで CSS 3.0 を選択する。
※ただし、設定維持の動作がおかしく、aspx ファイルを開くと CSS 2.1 に戻されたりする

上記を行っても、いくつかの警告は残る。
  • @charset
  • 非対応プロパティ (ime-mode など)
  • 妥当でない CSS ハック

そこで、Visual Studio の設定により、CSS の警告を出さないようにすることができる。
※同時にプロパティの typo などを検出できなくなる点に注意
  1. メニューの [ツール] → [オプション] で、オプション画面を表示
  2. [テキスト エディター] → [CSS] → [その他]
  3. [エラーの検出]チェックを外す
    [CSS][その他]
  4. [OK]を押して設定を保存

2014年4月17日

.NET バージョン毎にプロジェクトを分けてソースを共有する

たまに、複数の .NET バージョンでモノが欲しい時がある。
その際、複数のプロジェクトファイル(.NET バージョン違い)に同じソース群を参照させる。
その手順のメモ。

※元となるプロジェクトファイルは「MyLibrary.csproj」、バージョンは .NET 4.0 とする。
  1. プロジェクトファイル(csproj/vbproj)を複製
    MyLibrary.csproj → MyLibrary_net35.csproj
  2. バージョン変更する方のプロジェクトファイルの /Project/PropertyGroup/TargetFrameworkVersion を変更
    ・MyLibrary_net35.csproj
    
    <Project ToolsVersion="4.0" DefaultTargets="Build"
             xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <PropertyGroup>
        <!-- 中略 -->
        <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
    
  3. 両方のプロジェクトファイルに /Project/PropertyGroup/BaseIntermediateOutputPath + BaseOutputPath を追加し、/Project/PropertyGroup[@Condition]/OutputPath を変更
    (中間ファイルとバイナリの出力先の変更)
    ・MyLibrary.csproj
    
    <Project ToolsVersion="4.0" DefaultTargets="Build"
             xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <PropertyGroup>
        <BaseIntermediateOutputPath>obj\net40\</BaseIntermediateOutputPath>
        <BaseOutputPath>bin\net40\</BaseOutputPath>
    
    ・MyLibrary_net35.csproj
    
    <Project ToolsVersion="4.0" DefaultTargets="Build"
             xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <PropertyGroup>
        <BaseIntermediateOutputPath>obj\net35\</BaseIntermediateOutputPath>
        <BaseOutputPath>bin\net35\</BaseOutputPath>
    
    ・両方
    
    <Project ToolsVersion="4.0" DefaultTargets="Build"
             xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <!-- 中略 -->
      <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == '{構成設定}' "">
        <!-- 中略 -->
        <!-- 必要に応じて $(Platform) もパスに組み込む(マルチプラットフォーム等) -->
        <OutputPath>$(BaseOutputPath)\$(Configuration)\</OutputPath>
    
  4. Visual Studio で変更したプロジェクトファイルを再読込
  5. Visual Studio で複製したプロジェクトファイルを追加読込
    ソリューションを右クリック → [追加] → [既存のプロジェクト]
  6. .NET のバージョンに合わせたコード修正

備考

バイナリ出力先を分けるのは当然として、中間ファイル出力先を分けておかないと、Visual Studio の挙動がおかしくなることがある。リビルドでないと、ビルド成功しなかったり・・・
※複数プロジェクトで中間ファイル出力先がかぶることは、Visual Studio でビルド失敗する原因の 1 つ

中間ファイル出力先は、IntermediateOutputPath で構成設定毎に指定することも可能。
ただし、中間ファイル出力先を変更しても、「obj\Debug」「obj\Release」などのフォルダは作られる・・・

参考URL

2014年4月11日

Visual Studio の VB.NET 開発で、最初にやって欲しいこと

最初に 1 回だけ設定すると、幸せになれる。(個人差あり)
  1. Visual Studio を起動する。
  2. メニューの [ツール] → [オプション] で、オプション画面を表示
  3. [プロジェクトおよびソリューション] → [Visual Basic の規定値] を選択
  4. 画像のように設定
    ※デフォルトは Option Strict「Off」
    [Visual Basic の規定値]
  5. [OK]を押して設定を保存

効果

VB.NET プロジェクトを新規作成する際、プロジェクトプロパティのデフォルトが上記となる。
これで、毎回 Option Strict「On」にする必要も、変更し忘れる心配も無し♪♪

※本稿は VS 2010 での話だが、VS 2013 でもデフォルトは Option Strict「Off」のまま・・・たぶん今後も変わらないのだろう

2014年3月28日

C# と VB のちゃんぽん

C#.NET と VB.NET のプロジェクト(csproj/vbproj)を 1 つソリューション(sln)に含めることができる。
同じ IL を生成するので当然といえば当然なんだが、IDE のデメリットが多いため、オススメしない。

Visual Studio 2010 の場合、言語が異なるプロジェクトに対して、下記の不便がある。
  • 参照先をビルドしてないと、インテリセンスが効かない
  • 「定義へ移動」で、ソース本体に移動せず、定義が表示される
  • 「すべての参照を検索」で、検索されない

要は、プロジェクト参照なのに、実質、DLL 参照状態になる。
特別な理由がない限り、ちゃんぽんは避けるべき・・・

※デバッグ実行については、ちゃんぽんでも追ってくれる