はじめに
xUnit で [Theory]
を指定するテストメソッドでは [InlineData()]
を使用して、複数のテストケースを記述できます。
ですが引数が多くなってくると面倒で、楽をしたくなります。
いつものごとく、コードジェネレータを作成します。
コードジェネレータ
左の入力欄に、サンプルのように TSV 文字列をコピペして、convert ボタンをクリックしてください。右の入力欄に、生成した C# のコードが出力されます。
サンプル文字列が既に入力されているので、convert ボタンをクリックするだけで動作を確認できます。
生成されるコード例
以下のようなコードが出力されます。
[Theory()] [InlineData(1, "Apple", 200)] [InlineData(2, "Banana", 150)] [InlineData(3, "Citrus", 300)] public void TestMethod(int Id, string Name, int Price)
オプション
オプションが二つあり、チェックボックスで有効/無効を切り替えます。
Use CamelCase
チェックすると、メソッドの引数部分の識別子をキャメルケースにします。
Use String
チェックすると、全ての引数を文字列としてコードを生成します。
ソースコード
念のため、ソースコードも載っけておきます。JSFiddle がサービス終了しちゃうかもしれませんからね。
それに、オフラインで使いたいという要件もあるかもしれません(その場合、CDN のところは修正してください)。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>TSV (from Excel or other) to xUnit InlineData Definition</title> <style> .outer { display: flex; justify-content: center; align-items: center; } #app { margin: 0 auto; display: inline-block; text-align: left; height: 95%; } textarea { font-family: monospace; } @media (prefers-color-scheme: dark) { body { background-color: #333; color: #fff; } textarea { background-color: #444; color: #fff; } } </style> </head> <body> <div class="outer"> <div id="app"> <table> <tr> <td rowspan="3"> <textarea name="" id="src" cols="30" rows="10" v-model="src" placeholder="Excel などからコピペしてください"></textarea> </td> <td></td> <td rowspan="3"> <textarea name="" id="result" cols="30" rows="10" v-model="result"></textarea> </td> </tr> <tr> <td> <input type="checkbox" id="useCamelCase" v-model="useCamelCase" /> <label for="useCamenCase">Use CamelCase</label> <br /> <input type="checkbox" id="useString" v-model="useString" /> <label for="useString">Use String</label> <br /> </td> </tr> <tr> <td> <button v-on:click="convert">convert</button><br /> <button v-on:click="copyResult">copy</button> </td> </tr> </table> </div> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> <script> var vm = new Vue({ el: "#app", data: { src: "Id\tName\tPrice\n1\tApple\t200\n2\tBanana\t150\n3\tCitrus\t300", result: "", ln: "grid", useCamelCase: true, useString: false, }, methods: { convert: function (e) { let ret = ''; let lines = this.getLines(); const useCC = this.useCamelCase; const useStr = this.useString; // create header ret = "[Theory()]\n"; lines.forEach((line, row) => { if (row === 0) {return;} var csv = []; line.forEach((col, idx) => { if (useStr || isNaN(col)) { csv.push('"' + col + '"'); } else { csv.push(col); } }); ret += "[InlineData(" + csv.join(', ') + ")]\n"; }); // create types let types = []; const isInt = function (src) { const n = Number.parseFloat(src); return Number(n) === n && n % 1 === 0; }; lines[1].forEach((col, idx) => { if (!this.useString && !isNaN(col)) { if (isInt(col)) { types.push('int'); } else { types.push('double'); } } else { types.push('string'); } }); // create method ret += 'public void TestMethod('; var params = []; lines[0].forEach((col, idx) => { if (useCC) {col = this.camelCase(col);} params.push(types[idx] + ' ' + col); }); ret += params.join(', '); ret += ")\n"; this.result = ret; }, getLines: function () { var linesSrc = this.src.split("\n"); var lines = []; linesSrc.forEach(line => { if (line.trim() ==='') {return;} lines.push(line.trim().split("\t")); }); return lines; }, camelCase: function (str){ // http://webdesign-dackel.com/2015/05/15/js-change-case/ str = String(str); str = str.charAt(0).toLowerCase() + str.slice(1); return str.replace(/[-_](.)/g, function(match, group1) { return String(group1).toUpperCase(); }); }, copyResult: function () { navigator.clipboard .writeText(this.result) .then(() => { console.log('copied!') }) .catch(e => { console.error(e) }); } } }); </script> </body> </html>
最後に
2021-11-30 バグ修正。
なんか Edge だとコピーができない。