Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
root = true

# Общие настройки
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true

# C#-файлы
[*.cs]
indent_size = 4

# --- Форматирование (валидные правила Roslyn) ---
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_members_in_anonymous_types = true

csharp_prefer_braces = true:suggestion
csharp_prefer_simple_using_statement = true:suggestion

# --- Пробелы ---
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_around_binary_operators = before_and_after
csharp_space_between_parentheses = false
csharp_space_between_empty_square_brackets = false
csharp_space_before_colon_in_inheritance_clause = true

# --- Стиль кода ---
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion

csharp_style_var_for_built_in_types = true:suggestion
csharp_style_var_when_type_is_apparent = true:suggestion
csharp_style_var_elsewhere = false:suggestion

# --- Именование (Microsoft-style) ---

# private / private readonly поля: _camelCase
dotnet_naming_rule.private_fields.severity = suggestion
dotnet_naming_rule.private_fields.symbols = private_fields
dotnet_naming_rule.private_fields.style = camel_case_underscore

dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private

dotnet_naming_style.camel_case_underscore.capitalization = camel_case
dotnet_naming_style.camel_case_underscore.required_prefix = _

# public/internal/protected члены: PascalCase
dotnet_naming_rule.public_members.severity = suggestion
dotnet_naming_rule.public_members.symbols = public_members
dotnet_naming_rule.public_members.style = pascal_case

dotnet_naming_symbols.public_members.applicable_kinds = property,method,field,event,delegate
dotnet_naming_symbols.public_members.applicable_accessibilities = public,protected,protected_internal,internal

dotnet_naming_style.pascal_case.capitalization = pascal_case

# параметры и локальные переменные: camelCase
dotnet_naming_rule.parameters_and_locals.severity = suggestion
dotnet_naming_rule.parameters_and_locals.symbols = parameters_and_locals
dotnet_naming_rule.parameters_and_locals.style = camel_case

dotnet_naming_symbols.parameters_and_locals.applicable_kinds = parameter,local
dotnet_naming_symbols.parameters_and_locals.applicable_accessibilities = *

dotnet_naming_style.camel_case.capitalization = camel_case
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,9 @@ $RECYCLE.BIN/
.DS_Store

_NCrunch*

# =========================
# IDE
# =========================
.idea
.vs/
5 changes: 5 additions & 0 deletions Basics.Tests/Basics.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1"/>
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.16.1.129956">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="xunit" Version="2.9.3"/>
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.2" />
</ItemGroup>

<ItemGroup>
Expand Down
187 changes: 183 additions & 4 deletions Basics.Tests/StringFormatterTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ public void FormatName_WithValidNames_ReturnsFormattedString()
{
// Arrange
var formatter = new StringFormatter();
string firstName = "John";
string lastName = "Doe";
var firstName = "John";
var lastName = "Doe";

// Act
var result = formatter.FormatName(firstName, lastName);
Expand All @@ -33,5 +33,184 @@ public void SetPrefix_ChangesPrefixInFormatting()
// Assert
Assert.Equal("TEST: Jane Smith", result);
}

};

// === Дополнительные тесты для FormatName ===

[Fact]
public void FormatName_WithEmptyFirstName_ReturnsCorrectFormat()
{
// Arrange
var formatter = new StringFormatter();

// Act
var result = formatter.FormatName("", "Doe");

// Assert
Assert.Equal("DEFAULT: Doe", result); // пробел перед "Doe"
}

[Fact]
public void FormatName_WithEmptyLastName_ReturnsCorrectFormat()
{
// Arrange
var formatter = new StringFormatter();

// Act
var result = formatter.FormatName("John", "");

// Assert
Assert.Equal("DEFAULT: John ", result);
}

[Fact]
public void FormatName_WithBothNamesEmpty_ReturnsCorrectFormat()
{
// Arrange
var formatter = new StringFormatter();

// Act
var result = formatter.FormatName("", "");

// Assert
Assert.Equal("DEFAULT: ", result);
}

[Fact]
public void FormatName_AfterSetPrefixToNull_UsesEmptyStringAsPrefix()
{
// Arrange
var formatter = new StringFormatter();
formatter.SetPrefix(null);

// Act
var result = formatter.FormatName("A", "B");

// Assert
Assert.Equal(": A B", result); // null → ""
}

// === Тесты для CreateEmail ===

[Fact]
public void CreateEmail_WithValidUserNameAndDomain_ReturnsCorrectEmail()
{
// Act
var email = StringFormatter.CreateEmail("john.doe", "example.com");

// Assert
Assert.Equal("john.doe@example.com", email);
}

[Fact]
public void CreateEmail_WithEmptyUserName_ReturnsEmailStartingWithAt()
{
// Act
var email = StringFormatter.CreateEmail("", "example.com");

// Assert
Assert.Equal("@example.com", email);
}

[Fact]
public void CreateEmail_WithEmptyDomain_ReturnsEmailEndingWithAt()
{
// Act
var email = StringFormatter.CreateEmail("user", "");

// Assert
Assert.Equal("user@", email);
}

[Fact]
public void CreateEmail_WithBothEmpty_ReturnsOnlyAt()
{
// Act
var email = StringFormatter.CreateEmail("", "");

// Assert
Assert.Equal("@", email);
}

// === Тесты для RepeatString ===

[Fact]
public void RepeatString_WithPositiveCount_RepeatsCorrectly()
{
// Act
var result = StringFormatter.RepeatString("abc", 3);

// Assert
Assert.Equal("abcabcabc", result);
}

[Fact]
public void RepeatString_WithZeroCount_ReturnsEmptyString()
{
// Act
var result = StringFormatter.RepeatString("abc", 0);

// Assert
Assert.Equal("", result);
}

[Fact]
public void RepeatString_WithNegativeCount_ReturnsEmptyString()
{
// Act
var result = StringFormatter.RepeatString("abc", -5);

// Assert
Assert.Equal("", result);
}

[Fact]
public void RepeatString_WithEmptyInput_ReturnsEmptyString()
{
// Act
var result = StringFormatter.RepeatString("", 5);

// Assert
Assert.Equal("", result);
}

[Fact]
public void RepeatString_WithNullInput_ReturnsEmptyString()
{
// Act
var result = StringFormatter.RepeatString(string.Empty, 3);

// Assert
Assert.Equal("", result);
}

[Fact]
public void RepeatString_WithSingleCharacter_RepeatsCorrectly()
{
// Act
var result = StringFormatter.RepeatString("x", 4);

// Assert
Assert.Equal("xxxx", result);
}

// === Дополнительно: проверка независимости экземпляров ===

[Fact]
public void MultipleInstances_DoNotInterfereWithEachOther()
{
// Arrange
var formatter1 = new StringFormatter();
var formatter2 = new StringFormatter();

// Act
formatter1.SetPrefix("A");
formatter2.SetPrefix("B");

var result1 = formatter1.FormatName("X", "Y");
var result2 = formatter2.FormatName("X", "Y");

// Assert
Assert.Equal("A: X Y", result1);
Assert.Equal("B: X Y", result2);
}
}
10 changes: 10 additions & 0 deletions Basics/Basics.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@
<RootNamespace>Basics_0</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<AnalysisLevel>latest</AnalysisLevel>
</PropertyGroup>

<ItemGroup>
<!-- Анализатор Sonar -->
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.16.1.129956">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

</Project>
16 changes: 10 additions & 6 deletions Basics/Models/User.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,28 @@ namespace Basics_0.Models;

public class User
{
public int id;
public string Name;
private readonly int _id;
private readonly string _name;
private string _email;

public User()
{
id = 0;
Name = "Unknown";
_id = 0;
_name = "Unknown";
_email = "";
}

public string GetInfo()
{
return $"User: {Name}, ID: {id}";
return $"User: {_name}, ID: {_id}";
}

public void SetEmail(string email)
{
_email = email;
}
}
public string GetEmail()
{
return _email;
}
}
6 changes: 5 additions & 1 deletion Basics/Program.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// See https://aka.ms/new-console-template for more information

Console.WriteLine("Hello, World!");
using Basics_0.Services;

var str = StringFormatter.RepeatString("Привет! ", 3);

Console.WriteLine("Hello, World!" + " " + str);
Loading