I recently have been applying for jobs and so I decided to set up a modern .NET environment on Ubuntu with emacs and look into a unit testing suite called XUnit.

Setup

Emacs

omnisharp package installation

1
(package-install 'omnisharp)

c# configuration

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
(progn
  ;; c sharp
  ;; (add-hook 'csharp-mode-hook 'omnisharp-mode)
  ;; (add-hook 'csharp-mode-hook #'company-mode)
  ;; (add-hook 'csharp-mode-hook #'flycheck-mode)

  (eval-after-load
      'company
    '(add-to-list 'company-backends 'company-omnisharp))

  (defun my-csharp-mode-setup ()
    (omnisharp-mode)
    (company-mode)
    (flycheck-mode)

    (setq indent-tabs-mode nil)
    (setq c-syntactic-indentation t)
    (c-set-style "ellemtel")
    (setq c-basic-offset 4)
    (setq truncate-lines t)
    (setq tab-width 4)
    (setq evil-shift-width 4)

                                        ;csharp-mode README.md recommends this too
                                        ;(electric-pair-mode 1)       ;; Emacs 24
                                        ;(electric-pair-local-mode 1) ;; Emacs 25

    (local-set-key (kbd "C-c r r") 'omnisharp-run-code-action-refactoring)
    (local-set-key (kbd "C-c C-c") 'recompile))

  (add-hook 'csharp-mode-hook 'my-csharp-mode-setup t))

Roslyn

Download and build roslyn

https://github.com/OmniSharp/omnisharp-roslyn

1
cd "$MYGIT/OmniSharp/omnisharp-roslyn"; bash build.sh
  • Results
After successfully building, I can't run `omnisharp` because the `build.sh` script does not install.

Download and install a prebuilt binary

https://github.com/OmniSharp/omnisharp-roslyn/releases https://github.com/OmniSharp/omnisharp-roslyn/releases/download/v1.34.5/omnisharp-linux-x64.tar.gz

This is enlightening on how to set up omnisharp. The build readme was vague, but seeing the deployed tarball gets you to the point.

asciinema recording

  • Results

Install mono

https://www.mono-project.com/

https://www.mono-project.com/download/stable/

DONE I must uninstall chicken scheme to install mono

DONE I uninstalled it

This was the only way.

DISCARD Instead, simply rename the chicken scheme binary.

1
sudo mv /usr/bin/csc /usr/bin/chicken-csc

Install server

M-x omnisharp-install-server

Do something with .NET in emacs

Look for some c# koans

directory
$MYGIT/NotMyself/DotNetCoreKoans

https://github.com/NotMyself/DotNetCoreKoans

asciinema recording

It appears I need to install NuGet. This must be a package manager for csharp.

TODO Set up NuGet

Set up csharp

1
2
agi mono-csharp-shell
agi mono-dbg

Testing

XUnit

https://xunit.net/

Tutorial

https://dzone.com/articles/xunit-and-exceptions-with-async-task https://andrewlock.net/creating-parameterised-tests-in-xunit-with-inlinedata-classdata-and-memberdata/

Example test suite

1
$MYGIT/OmniSharp/omnisharp-roslyn/tests/OmniSharp.Cake.Tests/CakeProjectSystemFacts.cs
1
2
3
4
5
6
7
8
class OmniSharp.Cake.Tests.CakeProjectSystemFacts / (ctor) CakeProjectSystemFacts(ITestOutputHelper output)
class OmniSharp.Cake.Tests.CakeProjectSystemFacts / (method) AddFile(OmniSharpTestHost host, string filePath)
class OmniSharp.Cake.Tests.CakeProjectSystemFacts / (method) AllProjectsShouldUseLatestLanguageVersion()
class OmniSharp.Cake.Tests.CakeProjectSystemFacts / (method) DoesntParticipateInWorkspaceInfoResponseWhenDisable
class OmniSharp.Cake.Tests.CakeProjectSystemFacts / (method) GetWorkspaceInfoAsync(OmniSharpTestHost host)
class OmniSharp.Cake.Tests.CakeProjectSystemFacts / (method) RemoveFile(OmniSharpTestHost host, string filePath)
class OmniSharp.Cake.Tests.CakeProjectSystemFacts / (method) ShouldAddAndRemoveProjects()
class OmniSharp.Cake.Tests.CakeProjectSystemFacts / (method) ShouldGetProjects()

Example test

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
[Fact]
public async Task ShouldAddAndRemoveProjects()
{
    using (var testProject = await TestAssets.Instance.GetTestProjectAsync("CakeProject", shadowCopy : false))
    using (var host = CreateOmniSharpHost(testProject.Directory))
    {
        var tempFile = Path.Combine(testProject.Directory, "temp.cake");

        var workspaceInfo = await GetWorkspaceInfoAsync(host);
        Assert.Equal(3, workspaceInfo.Projects.Count());

        await AddFile(host, tempFile);
        workspaceInfo = await GetWorkspaceInfoAsync(host);
        Assert.Equal(4, workspaceInfo.Projects.Count());
        Assert.Contains("temp.cake", workspaceInfo.Projects.Select(p => Path.GetFileName(p.Path)));

        await RemoveFile(host, tempFile);
        workspaceInfo = await GetWorkspaceInfoAsync(host);
        Assert.Equal(3, workspaceInfo.Projects.Count());
        Assert.DoesNotContain("temp.cake", workspaceInfo.Projects.Select(p => Path.GetFileName(p.Path)));
    }
}
  • Questions
-    What is a `Fact`?

    xUnit uses the [Fact] attribute to denote a
    parameterless unit test, which tests
    invariants in your code.

-    What is a `Theory`?

    In contrast, the
    [Theory] attribute denotes a parameterised
    test that is true for a subset of data. That
    data can be supplied in a number of ways, but
    the most common is with an `[InlineData]`
    attribute.

    <https://andrewlock.net/creating-parameterised-tests-in-xunit-with-inlinedata-classdata-and-memberdata/>

    You use `Theory` to create parameterised tests with `[InlineData]`.

    
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
        [Theory]
        [InlineData(1, 2, 3)]
        [InlineData(-4, -6, -10)]
        [InlineData(-2, 2, 0)]
        [InlineData(int.MinValue, -1, int.MaxValue)]
        public void CanAddTheory(int value1, int value2, int expected)
        {
            var calculator = new Calculator();

            var result = calculator.Add(value1, value2);

            Assert.Equal(expected, result);
        }
        
- What is a `Task`? It's a thread defined in the standard libraries.
1
2
        using System.Threading.Tasks;