目的
- 完全に私用です
- C#の勉強も兼ねて作りました
- あと、Qiitaに何か投稿してみたかった!(これが一番大きい)
言語
- C#6.0 で書いてます
使い方
- Visual Stdio 2015であらかじめ、Atcoderというコンソールプロジェクトを作成し、右クリックで"単体テストの作成"をしておく
- 次にVisual Studio 2015で新しいC#のコンソールプロジェクトを作成し、以下のコード(Program.cs)を貼り付けて実行
- "Input Atcoder Problem URL : "が出てきたら、問題ページのURLを入力
- 実行ファイルがあるディレクトリに、"ProgramTests.cs"というファイルが作成されたら多分成功
- Atcoderプロジェクトの"PrgmramTests.cs"に4で作成されたファイルをコピーして終わり
(Atcoderプロジェクトの"ProgramTests.cs"があるフォルダで、テストケース取得プログラムを起動すれば5の動作が省けて楽です)
ソースコード
Program.cs
using System.Text;
using System.Net;
using System.Text.RegularExpressions;
using static System.Console;
using System.IO;
namespace getTestcaseForAtcoder
{
class Program
{
static void Main(string[] args)
{
WriteLine("Input Atcoder Problem URL : ");
string testcases = getTestCase(getContext(ReadLine().Trim(new char[]{'\r', '\n', ' '})));
using (StreamWriter sw = new StreamWriter("ProgramTests.cs"))
{
sw.Write(testcases);
}
WriteLine("Output to \"ProgramTests.cs\"");
}
static string getTestCase(string html)
{
string source1 =
@"using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;
namespace Atcoder.Tests
{
[TestClass()]
public class ProgramTests
{
(TESTCASES)
private void AssertIO(string input, string output)
{
StringReader reader = new StringReader(input);
Console.SetIn(reader);
StringWriter writer = new StringWriter();
Console.SetOut(writer);
Program.Main(new string[0]);
Assert.AreEqual(output + Environment.NewLine, writer.ToString());
}
}
}";
string source2 = @"
[TestMethod()]
[Timeout(2000)]
public void Test(TESTNUM)()
{
string input = ""(TESTCASE1)"";
string output = ""(TESTCASE2)"";
AssertIO(input, output);
}";
string anchor = "(<pre class=\"prettyprint linenums\">|<pre>)(?<testcase>.*?)</pre>";
Regex re = new Regex(anchor, RegexOptions.IgnoreCase | RegexOptions.Singleline);
StringBuilder sb = new StringBuilder();
int i = 1;
for (Match m = re.Match(html); m.Success; m = m.NextMatch())
{
if (m.Groups["testcase"].Value.Contains("<var>")) continue;
string testCase1 = m.Groups["testcase"].Value; m = m.NextMatch();
string testCase2 = m.Groups["testcase"].Value;
testCase1 = testCase1.TrimStart('\r').TrimStart('\n').Replace("\r", "").Replace("\n", "\\n");
testCase2 = testCase2.TrimStart('\r').TrimStart('\n').TrimEnd('\n').TrimEnd('\r').Replace("\r", "").Replace("\n", "\\n");
sb.AppendLine(source2.Replace("(TESTNUM)", (i++).ToString()).Replace("(TESTCASE1)", testCase1).Replace("(TESTCASE2)", testCase2));
}
return source1.Replace("(TESTCASES)", sb.ToString());
}
static string getContext(string url)
{
WebClient wc = new WebClient();
byte[] data = wc.DownloadData(url);
Encoding enc = Encoding.GetEncoding("utf-8");
string ret = enc.GetString(data);
wc.Dispose();
return ret;
}
}
}
使用例
ABC001コンテストのA問題を使ってテストしてみます。
実行例
Input Atcoder Problem URL :
http://abc001.contest.atcoder.jp/tasks/abc001_1
Output to \"ProgramTests.cs\"
生成されたファイル
ProgramTests.cs
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;
namespace Atcoder.Tests
{
[TestClass()]
public class ProgramTests
{
[TestMethod()]
[Timeout(2000)]
public void Test1()
{
string input = "15\n10\n";
string output = "5";
AssertIO(input, output);
}
[TestMethod()]
[Timeout(2000)]
public void Test2()
{
string input = "0\n0\n";
string output = "0";
AssertIO(input, output);
}
[TestMethod()]
[Timeout(2000)]
public void Test3()
{
string input = "5\n20\n";
string output = "-15";
AssertIO(input, output);
}
private void AssertIO(string input, string output)
{
StringReader reader = new StringReader(input);
Console.SetIn(reader);
StringWriter writer = new StringWriter();
Console.SetOut(writer);
Program.Main(new string[0]);
Assert.AreEqual(output + Environment.NewLine, writer.ToString());
}
}
}
まとめ
- 入出力のテストが楽になりました
変更履歴
- 2015/11/24 公開
- 2015/11/24 コードの訂正
- 2015/11/25 getTestCase関数内でアドバイスを頂いた部分の修正
注意事項
- エラー処理は行ってません
- 出力との比較は文字列の完全一致です
- コンテスト中の問題は取得できない可能性があります(認証が必要?)